FIX: Update first_pm_unread_at of user's groups without unread.

If a user always read all group messages, we will never update the
`first_pm_unread_at` column since the previous query will not return the
group_user. Instead, we should update `first_pm_unread_at` to the
current timestamp if the user has read everything.

Follow-up to 9b75d95fc6
This commit is contained in:
Guo Xiang Tan 2020-09-10 17:13:11 +08:00
parent 122cf8d3fb
commit f27de87bf3
No known key found for this signature in database
GPG Key ID: FBD110179AAC1F20
2 changed files with 32 additions and 21 deletions

View File

@ -24,7 +24,7 @@ class GroupUser < ActiveRecord::Base
end
def self.update_first_unread_pm(last_seen, limit: 10_000)
DB.exec(<<~SQL, archetype: Archetype.private_message, last_seen: last_seen, limit: limit)
DB.exec(<<~SQL, archetype: Archetype.private_message, last_seen: last_seen, limit: limit, now: 10.minutes.ago)
UPDATE group_users gu
SET first_unread_pm_at = Y.min_date
FROM (
@ -34,23 +34,30 @@ class GroupUser < ActiveRecord::Base
X.min_date
FROM (
SELECT
gu2.group_id,
gu2.user_id,
MIN(t.updated_at) min_date
FROM group_users gu2
INNER JOIN topic_allowed_groups tag ON tag.group_id = gu2.group_id
INNER JOIN topics t ON t.id = tag.topic_id
INNER JOIN users u ON u.id = gu2.user_id
LEFT JOIN topic_users tu ON t.id = tu.topic_id AND tu.user_id = gu2.user_id
WHERE t.deleted_at IS NULL
AND t.archetype = :archetype
AND tu.last_read_post_number < CASE
WHEN u.admin OR u.moderator
THEN t.highest_staff_post_number
ELSE t.highest_post_number
END
AND (COALESCE(tu.notification_level, 1) >= 2)
GROUP BY gu2.user_id, gu2.group_id
gu.group_id,
gu.user_id,
COALESCE(Z.min_date, :now) min_date
FROM group_users gu
LEFT JOIN (
SELECT
gu2.group_id,
gu2.user_id,
MIN(t.updated_at) min_date
FROM group_users gu2
INNER JOIN topic_allowed_groups tag ON tag.group_id = gu2.group_id
INNER JOIN topics t ON t.id = tag.topic_id
INNER JOIN users u ON u.id = gu2.user_id
LEFT JOIN topic_users tu ON t.id = tu.topic_id AND tu.user_id = gu2.user_id
WHERE t.deleted_at IS NULL
AND t.archetype = :archetype
AND tu.last_read_post_number < CASE
WHEN u.admin OR u.moderator
THEN t.highest_staff_post_number
ELSE t.highest_post_number
END
AND (COALESCE(tu.notification_level, 1) >= 2)
GROUP BY gu2.user_id, gu2.group_id
) AS Z ON Z.user_id = gu.user_id AND Z.group_id = gu.group_id
) AS X
WHERE X.user_id IN (
SELECT id

View File

@ -163,6 +163,7 @@ describe GroupUser do
describe '#ensure_consistency!' do
fab!(:group) { Fabricate(:group) }
fab!(:group_2) { Fabricate(:group) }
fab!(:pm_post) { Fabricate(:private_message_post) }
@ -173,6 +174,7 @@ describe GroupUser do
fab!(:user) do
Fabricate(:user, last_seen_at: Time.zone.now).tap do |u|
group.add(u)
group_2.add(u)
TopicUser.change(u.id, pm_topic.id,
notification_level: TopicUser.notification_levels[:tracking],
@ -213,11 +215,13 @@ describe GroupUser do
topic_id: pm_topic.id
)
GroupUser.ensure_consistency!
expect { GroupUser.ensure_consistency! }
.to_not change { group.group_users.find_by(user_id: user_3.id).first_unread_pm_at }
expect(post.topic.updated_at).to_not eq(10.minutes.ago)
expect(group.group_users.find_by(user_id: user.id).first_unread_pm_at).to eq_time(post.topic.updated_at)
expect(group.group_users.find_by(user_id: user_2.id).first_unread_pm_at).to_not eq_time(post.topic.updated_at)
expect(group.group_users.find_by(user_id: user_3.id).first_unread_pm_at).to_not eq_time(post.topic.updated_at)
expect(group_2.group_users.find_by(user_id: user.id).first_unread_pm_at).to eq_time(10.minutes.ago)
expect(group.group_users.find_by(user_id: user_2.id).first_unread_pm_at).to eq_time(10.minutes.ago)
end
end
end