PERF: Update like count in visible posts without an extra GET per like (#14869)
PERF: Update like count in visible posts without an extra GET per like Currently when a user is reading a topic and some post in it receive a like from another user, the Ember app will be notified via MessageBus and issue a GET to `/posts/{id}` to get the new like count. This worked fine for us until today, but it can easily create a self-inflicted DDoS when a topic with a large number of visitors gets a large number of likes, since we will issue `visitors * likes` GET requests requests. This patch optimizes this flow, by sending the new like count down in the MessageBus notification, removing any need for the extra request. It shouldn't cause any drift on the count because we send down the full count instead of the difference too. Possible follow-ups could include handling like removal.
This commit is contained in:
parent
b72688340f
commit
d4e35f50c2
|
@ -1598,6 +1598,12 @@ export default Controller.extend(bufferedProperty("model"), {
|
|||
.then(() => refresh({ id: data.id, refreshLikes: true }));
|
||||
break;
|
||||
}
|
||||
case "liked": {
|
||||
postStream
|
||||
.triggerLikedPost(data.id, data.likes_count)
|
||||
.then(() => refresh({ id: data.id, refreshLikes: true }));
|
||||
break;
|
||||
}
|
||||
case "revised":
|
||||
case "rebaked": {
|
||||
postStream
|
||||
|
|
|
@ -847,6 +847,18 @@ export default RestModel.extend({
|
|||
return resolved;
|
||||
},
|
||||
|
||||
triggerLikedPost(postId, likesCount) {
|
||||
const resolved = Promise.resolve();
|
||||
|
||||
const post = this.findLoadedPost(postId);
|
||||
if (post) {
|
||||
post.updateLikeCount(likesCount);
|
||||
this.storePost(post);
|
||||
}
|
||||
|
||||
return resolved;
|
||||
},
|
||||
|
||||
triggerReadPost(postId, readersCount) {
|
||||
const resolved = Promise.resolve();
|
||||
resolved.then(() => {
|
||||
|
|
|
@ -355,6 +355,37 @@ const Post = RestModel.extend({
|
|||
}
|
||||
},
|
||||
|
||||
updateLikeCount(count) {
|
||||
let current_actions_summary = this.get("actions_summary");
|
||||
let likeActionID = Site.current().post_action_types.find(
|
||||
(a) => a.name_key === "like"
|
||||
).id;
|
||||
|
||||
if (!this.actions_summary.find((entry) => entry.id === likeActionID)) {
|
||||
let json = Post.munge({
|
||||
id: this.id,
|
||||
actions_summary: [
|
||||
{
|
||||
id: likeActionID,
|
||||
count,
|
||||
},
|
||||
],
|
||||
});
|
||||
this.set(
|
||||
"actions_summary",
|
||||
Object.assign(current_actions_summary, json.actions_summary)
|
||||
);
|
||||
this.set("actionByName", json.actionByName);
|
||||
this.set("likeAction", json.likeAction);
|
||||
} else {
|
||||
this.actions_summary.find(
|
||||
(entry) => entry.id === likeActionID
|
||||
).count = count;
|
||||
this.actionByName["like"] = count;
|
||||
this.likeAction.count = count;
|
||||
}
|
||||
},
|
||||
|
||||
revertToRevision(version) {
|
||||
return ajax(`/posts/${this.id}/revisions/${version}/revert`, {
|
||||
type: "PUT",
|
||||
|
|
|
@ -156,13 +156,15 @@ private
|
|||
end
|
||||
|
||||
def notify_subscribers
|
||||
if self.class.notify_types.include?(@post_action_name)
|
||||
if @post_action_name == :like
|
||||
@post.publish_change_to_clients! :liked, { likes_count: @post.like_count + 1 }
|
||||
elsif self.class.notify_types.include?(@post_action_name)
|
||||
@post.publish_change_to_clients! :acted
|
||||
end
|
||||
end
|
||||
|
||||
def self.notify_types
|
||||
@notify_types ||= ([:like] + PostActionType.notify_flag_types.keys)
|
||||
@notify_types ||= PostActionType.notify_flag_types.keys
|
||||
end
|
||||
|
||||
def enforce_rules
|
||||
|
|
Loading…
Reference in New Issue