我正在做一个酒店预订项目。一项新功能要求客户可以对酒店发表评论。每条评论都有一个等级(0 --> 5)。在搜索酒店页面上,每家酒店都会显示其平均评分。
添加评论非常简单,可以发布一个 CommentAddedEvent:
class CommentAddedEvent {
private String hotelId;
private double rating;
//other attributes omitted
}
在查询方面,此事件上会保留一个注释行:
create table t_comment {
hotel_id number,
rating number(2,1)
}
但是我们在如何显示酒店的平均评分方面放慢了速度。以下是我们可能的解决方案:
a) 数据库集成
在搜索酒店查询端,使用 sql 函数获取平均值:
select h.id, h.name,....,select avg(c.rating) from t_commentc , t_hotel
where.... group by c.hotel_id.....
这看起来很简单,但我们认为它会在测试中引入更多的精力,并且可能会导致一些性能问题。
b) EventHandler 计算平均值
添加一个订阅 CommentAddedEvent 的事件处理程序并计算平均值:
public void on(CommentAddedEvent event) {
Hotel hotel = ....
double total = hotel.rating * hotel.comments;
double average = (total + event.rating)/(hotel.comments + 1)
//update hotel
}
测试很简单,但这个解决方案似乎不是幂等的。当某些事情失败时,事件处理程序可能会处理重复事件。
c) 计划任务
添加定时任务,汇总每家酒店的意见。但这对于一些酒店来说效率很低,因为上次任务后没有评论。
d) 计划任务与事件处理程序混合
使用事件处理程序来标记自上次任务以来评论的酒店:
public void on(CommentAddedEvent event) {
int count = uncalculatedCommentsOnHotel(...);
count++;
//update count
}
并根据计数大于零的酒店安排摘要任务。
解决方案 D 是幂等的,并且似乎更有效。我们是否存在一些缺陷或任何其他解决方案?