PREF: speed up grabbing unread counts

This commit is contained in:
Sam 2015-04-17 16:01:20 +10:00
parent 832cb9fdc3
commit 51b747346e
2 changed files with 35 additions and 9 deletions

View file

@ -235,23 +235,51 @@ class User < ActiveRecord::Base
User.email_hash(email) User.email_hash(email)
end end
def unread_notifications_by_type
@unread_notifications_by_type ||= notifications.visible.where("id > ? and read = false", seen_notification_id).group(:notification_type).count
end
def reload def reload
@unread_notifications_by_type = nil @unread_notifications = nil
@unread_total_notifications = nil @unread_total_notifications = nil
@unread_pms = nil @unread_pms = nil
super super
end end
def unread_private_messages def unread_private_messages
@unread_pms ||= notifications.visible.where("read = false AND notification_type = ?", Notification.types[:private_message]).count @unread_pms ||=
begin
# perf critical, much more efficient than AR
sql = "
SELECT COUNT(*) FROM notifications n
LEFT JOIN topics t ON n.topic_id = t.id
WHERE
t.deleted_at IS NULL AND
n.notification_type = :type AND
n.user_id = :user_id AND
NOT read"
User.exec_sql(sql, user_id: id,
type: Notification.types[:private_message])
.getvalue(0,0).to_i
end
end end
def unread_notifications def unread_notifications
unread_notifications_by_type.except(Notification.types[:private_message]).values.sum @unread_notifications ||=
begin
# perf critical, much more efficient than AR
sql = "
SELECT COUNT(*) FROM notifications n
LEFT JOIN topics t ON n.topic_id = t.id
WHERE
t.deleted_at IS NULL AND
n.notification_type <> :pm AND
n.user_id = :user_id AND
NOT read AND
n.id > :seen_notification_id"
User.exec_sql(sql, user_id: id,
seen_notification_id: seen_notification_id,
pm: Notification.types[:private_message])
.getvalue(0,0).to_i
end
end end
def total_unread_notifications def total_unread_notifications

View file

@ -90,12 +90,10 @@ describe PostTiming do
PostAction.act(user2, post, PostActionType.types[:like]) PostAction.act(user2, post, PostActionType.types[:like])
expect(post.user.unread_notifications).to eq(1) expect(post.user.unread_notifications).to eq(1)
expect(post.user.unread_notifications_by_type).to eq({Notification.types[:liked] => 1 })
PostTiming.process_timings(post.user, post.topic_id, 1, [[post.post_number, 100]]) PostTiming.process_timings(post.user, post.topic_id, 1, [[post.post_number, 100]])
post.user.reload post.user.reload
expect(post.user.unread_notifications_by_type).to eq({})
expect(post.user.unread_notifications).to eq(0) expect(post.user.unread_notifications).to eq(0)
end end