FIX: Sync user's reviewables count when loading reviewables list (#20128)

1. What is the problem here?

When a user's reviewables count changes, the changes are published via
MessageBus in a background Sidekiq job which means there is a delay before the
client receives the MessageBus message with the updated count. During
the time the reviewables count for a user has been updated and the time
when the client receives the MessageBus message with the updated count,
a user may view the reviewables list in the user menu. When that happens, the number of
reviewables in the list may be out of sync with the count shown.

2. What is the fix?

Going forward, the response for the `ReviewablesController#user_menu_list` action will include the user's reviewables count as
the `reviewables_count` attribute. This is then used by the client side
to update the user's reviewables count to ensure that the reviewables
list and count are kept in sync.
This commit is contained in:
Alan Guo Xiang Tan 2023-02-02 10:19:51 +08:00 committed by GitHub
parent 4570118a63
commit ce531913a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 0 deletions

View File

@ -25,6 +25,8 @@ export default class UserMenuReviewablesList extends UserMenuItemsList {
fetchItems() {
return ajax("/review/user-menu-list").then((data) => {
this.currentUser.updateReviewableCount(data.reviewable_count);
return data.reviewables.map((item) => {
return new UserMenuReviewableItem({
reviewable: UserMenuReviewable.create(item),

View File

@ -120,9 +120,19 @@ acceptance("User menu", function (needs) {
test("clicking on user menu items", async function (assert) {
updateCurrentUser({ reviewable_count: 1 });
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-review-queue");
assert.strictEqual(
query(
"#user-menu-button-review-queue .badge-notification"
).textContent.trim(),
"8",
"updates user's reviewable count based on request's response"
);
await click("#quick-access-review-queue li.reviewable.pending a");
assert.strictEqual(

View File

@ -214,6 +214,7 @@ export default function (helpers) {
is_new_topic: false,
},
],
reviewable_count: 8,
__rest_serializer: "1",
});
});

View File

@ -81,6 +81,7 @@ class ReviewablesController < ApplicationController
Reviewable.user_menu_list_for(current_user),
current_user,
).as_json,
reviewable_count: current_user.reviewable_count,
}
render_json_dump(json, rest_serializer: true)
end

View File

@ -300,6 +300,16 @@ RSpec.describe ReviewablesController do
expect(reviewables[0]["pending"]).to eq(true)
end
it "responds with current user's reviewables count" do
reviewable = Fabricate(:reviewable)
get "/review/user-menu-list.json"
expect(response.status).to eq(200)
expect(response.parsed_body["reviewables"].length).to eq(1)
expect(response.parsed_body["reviewable_count"]).to eq(1)
end
it "responds with pending reviewables only" do
Fabricate(:reviewable, status: Reviewable.statuses[:approved])
pending1 = Fabricate(:reviewable, status: Reviewable.statuses[:pending])