discourse/app/jobs/regular/deliver_push_notification.rb
Rafael dos Santos Silva 75718576c6
DEV: Centralize push notification delivery into a single job (#39207)
## Summary

- Unifies the two parallel push notification delivery paths (web push
via VAPID and hub/native app relay) into a single
`DeliverPushNotification` job
- Extracts hub push delivery into `HubPushNotificationPusher` service,
symmetric with the existing `PushNotificationPusher` for web push
- Adds `UserApiKey.push_clients_for(user)` to encapsulate hub client
lookup previously inlined in PostAlerter
- Simplifies `PostAlerter.push_notification()` from two parallel enqueue
blocks to a single call
- Converts old jobs (`SendPushNotification`, `PushNotification`) to thin
delegators for Sidekiq backward compatibility with in-flight jobs

## Test plan

- [ ] `bin/rspec spec/jobs/deliver_push_notification_spec.rb` — new
unified job tests
- [ ] `bin/rspec spec/services/hub_push_notification_pusher_spec.rb` —
new hub pusher tests
- [ ] `bin/rspec spec/jobs/send_push_notification_spec.rb
spec/jobs/push_notification_spec.rb` — backward compat delegation
- [ ] `bin/rspec spec/services/post_alerter_spec.rb` — PostAlerter
integration
- [ ] `bin/rspec spec/services/push_notification_pusher_spec.rb` — web
push unchanged
- [ ] `bin/rspec
plugins/chat/spec/jobs/regular/chat/notify_watching_spec.rb
plugins/chat/spec/jobs/regular/chat/notify_mentioned_spec.rb` — chat
plugin callers
2026-04-14 11:55:45 -03:00

55 lines
1.7 KiB
Ruby

# frozen_string_literal: true
module Jobs
class DeliverPushNotification < ::Jobs::Base
def execute(args)
user = User.find_by(id: args[:user_id])
push_window = SiteSetting.push_notification_time_window_mins
if !user ||
(
!args[:bypass_time_window] && push_window > 0 &&
user.seen_since?(push_window.minutes.ago)
)
return
end
payload = args[:payload].with_indifferent_access
if SiteSetting.content_localization_enabled
I18n.with_locale(user.effective_locale) { localize_content!(payload) }
end
PushNotificationPusher.push(user, payload.deep_dup) if user.push_subscriptions.exists?
HubPushNotificationPusher.push(user, payload.deep_dup)
end
private
def localize_content!(payload)
locale = I18n.locale.to_s.sub("-", "_")
if (topic_id = payload[:topic_id])
topic_localization =
TopicLocalization.find_by(topic_id: topic_id, locale: locale) ||
TopicLocalization.matching_locale(locale).find_by(topic_id: topic_id)
payload[:topic_title] = topic_localization.title if topic_localization
end
if (post_id = payload[:post_id])
post_localization =
PostLocalization.find_by(post_id: post_id, locale: locale) ||
PostLocalization.matching_locale(locale).find_by(post_id: post_id)
if post_localization
payload[:excerpt] = Post.excerpt(
post_localization.cooked,
400,
text_entities: true,
strip_links: true,
remap_emoji: true,
plain_hashtags: true,
)
end
end
end
end
end