mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: handle all notification consolidations in new 'NotificationConsolidator' class.
481c8314f0
This commit is contained in:
88
app/services/notification_consolidator.rb
Normal file
88
app/services/notification_consolidator.rb
Normal file
@@ -0,0 +1,88 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class NotificationConsolidator
|
||||
attr_reader :notification, :notification_type, :consolidation_type, :data
|
||||
|
||||
def initialize(notification)
|
||||
@notification = notification
|
||||
@notification_type = notification.notification_type
|
||||
@data = notification.data_hash
|
||||
|
||||
if notification_type == Notification.types[:liked]
|
||||
@consolidation_type = Notification.types[:liked_consolidated]
|
||||
@data[:username] = @data[:display_username]
|
||||
elsif notification_type == Notification.types[:private_message]
|
||||
post_id = @data[:original_post_id]
|
||||
return if post_id.blank?
|
||||
|
||||
custom_field = PostCustomField.select(:value).find_by(post_id: post_id, name: "requested_group_id")
|
||||
return if custom_field.blank?
|
||||
|
||||
group_id = custom_field.value.to_i
|
||||
group_name = Group.select(:name).find_by(id: group_id)&.name
|
||||
return if group_name.blank?
|
||||
|
||||
@consolidation_type = Notification.types[:membership_request_consolidated]
|
||||
@data[:group_name] = group_name
|
||||
end
|
||||
end
|
||||
|
||||
def consolidate!
|
||||
return if SiteSetting.notification_consolidation_threshold.zero? || consolidation_type.blank?
|
||||
|
||||
update_consolidated_notification! || create_consolidated_notification!
|
||||
end
|
||||
|
||||
def update_consolidated_notification!
|
||||
consolidated_notification = user_notifications.filter_by_consolidation_data(consolidation_type, data).first
|
||||
return if consolidated_notification.blank?
|
||||
|
||||
data_hash = consolidated_notification.data_hash
|
||||
data_hash["count"] += 1
|
||||
|
||||
Notification.transaction do
|
||||
consolidated_notification.update!(
|
||||
data: data_hash.to_json,
|
||||
read: false,
|
||||
updated_at: timestamp
|
||||
)
|
||||
notification.destroy!
|
||||
end
|
||||
|
||||
consolidated_notification
|
||||
end
|
||||
|
||||
def create_consolidated_notification!
|
||||
notifications = user_notifications.unread.filter_by_consolidation_data(notification_type, data)
|
||||
return if notifications.count <= SiteSetting.notification_consolidation_threshold
|
||||
|
||||
consolidated_notification = nil
|
||||
|
||||
Notification.transaction do
|
||||
timestamp = notifications.last.created_at
|
||||
data[:count] = notifications.count
|
||||
|
||||
consolidated_notification = Notification.create!(
|
||||
notification_type: consolidation_type,
|
||||
user_id: notification.user_id,
|
||||
data: data.to_json,
|
||||
updated_at: timestamp,
|
||||
created_at: timestamp
|
||||
)
|
||||
|
||||
notifications.destroy_all
|
||||
end
|
||||
|
||||
consolidated_notification
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_notifications
|
||||
notification.user.notifications
|
||||
end
|
||||
|
||||
def timestamp
|
||||
@timestamp ||= Time.zone.now
|
||||
end
|
||||
end
|
||||
@@ -331,28 +331,19 @@ class PostAlerter
|
||||
|
||||
notification_data = {}
|
||||
|
||||
if is_liked
|
||||
if existing_notification_of_same_type &&
|
||||
existing_notification_of_same_type.created_at > 1.day.ago &&
|
||||
(
|
||||
user.user_option.like_notification_frequency ==
|
||||
UserOption.like_notification_frequency_type[:always]
|
||||
)
|
||||
if is_liked &&
|
||||
existing_notification_of_same_type &&
|
||||
existing_notification_of_same_type.created_at > 1.day.ago &&
|
||||
(
|
||||
user.user_option.like_notification_frequency ==
|
||||
UserOption.like_notification_frequency_type[:always]
|
||||
)
|
||||
|
||||
data = existing_notification_of_same_type.data_hash
|
||||
notification_data["username2"] = data["display_username"]
|
||||
notification_data["count"] = (data["count"] || 1).to_i + 1
|
||||
# don't use destroy so we don't trigger a notification count refresh
|
||||
Notification.where(id: existing_notification_of_same_type.id).destroy_all
|
||||
elsif !SiteSetting.likes_notification_consolidation_threshold.zero?
|
||||
notification = consolidate_liked_notifications(
|
||||
user,
|
||||
post,
|
||||
opts[:display_username]
|
||||
)
|
||||
|
||||
return notification if notification
|
||||
end
|
||||
data = existing_notification_of_same_type.data_hash
|
||||
notification_data["username2"] = data["display_username"]
|
||||
notification_data["count"] = (data["count"] || 1).to_i + 1
|
||||
# don't use destroy so we don't trigger a notification count refresh
|
||||
Notification.where(id: existing_notification_of_same_type.id).destroy_all
|
||||
end
|
||||
|
||||
collapsed = false
|
||||
@@ -625,82 +616,4 @@ class PostAlerter
|
||||
def warn_if_not_sidekiq
|
||||
Rails.logger.warn("PostAlerter.#{caller_locations(1, 1)[0].label} was called outside of sidekiq") unless Sidekiq.server?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def consolidate_liked_notifications(user, post, username)
|
||||
user_notifications = user.notifications
|
||||
|
||||
consolidation_window =
|
||||
SiteSetting.likes_notification_consolidation_window_mins.minutes.ago
|
||||
|
||||
liked_by_user_notifications =
|
||||
user_notifications
|
||||
.filter_by_display_username_and_type(
|
||||
username, Notification.types[:liked]
|
||||
)
|
||||
.where(
|
||||
"created_at > ? AND data::json ->> 'username2' IS NULL",
|
||||
consolidation_window
|
||||
)
|
||||
|
||||
user_liked_consolidated_notification =
|
||||
user_notifications
|
||||
.filter_by_display_username_and_type(
|
||||
username, Notification.types[:liked_consolidated]
|
||||
)
|
||||
.where("created_at > ?", consolidation_window)
|
||||
.first
|
||||
|
||||
if user_liked_consolidated_notification
|
||||
return update_consolidated_liked_notification_count!(
|
||||
user_liked_consolidated_notification
|
||||
)
|
||||
elsif (
|
||||
liked_by_user_notifications.count >=
|
||||
SiteSetting.likes_notification_consolidation_threshold
|
||||
)
|
||||
return create_consolidated_liked_notification!(
|
||||
liked_by_user_notifications,
|
||||
post,
|
||||
username
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def update_consolidated_liked_notification_count!(notification)
|
||||
data = notification.data_hash
|
||||
data["count"] += 1
|
||||
|
||||
notification.update!(
|
||||
data: data.to_json,
|
||||
read: false
|
||||
)
|
||||
|
||||
notification
|
||||
end
|
||||
|
||||
def create_consolidated_liked_notification!(notifications, post, username)
|
||||
notification = nil
|
||||
|
||||
Notification.transaction do
|
||||
timestamp = notifications.last.created_at
|
||||
|
||||
notification = Notification.create!(
|
||||
notification_type: Notification.types[:liked_consolidated],
|
||||
user_id: post.user_id,
|
||||
data: {
|
||||
username: username,
|
||||
display_username: username,
|
||||
count: notifications.count + 1
|
||||
}.to_json,
|
||||
updated_at: timestamp,
|
||||
created_at: timestamp
|
||||
)
|
||||
|
||||
notifications.each(&:destroy!)
|
||||
end
|
||||
|
||||
notification
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user