diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 3bda4ec04..ca6e25622 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -13,7 +13,7 @@ class MessagesController < ApplicationController end if @message.save begin - @message.delay.send_push + @message.send_push success = true rescue Pusher::Error => e logger.info "PUSHER ERROR: #{e.message}" diff --git a/app/jobs/messages/send_push_job.rb b/app/jobs/messages/send_push_job.rb new file mode 100644 index 000000000..8926057f1 --- /dev/null +++ b/app/jobs/messages/send_push_job.rb @@ -0,0 +1,14 @@ +module Messages + class SendPushJob < ApplicationJob + queue_as :messages_send_push + + def perform(user_id, chat_channel_id, message_html, service = Messages::SendPush) + user = User.find_by(id: user_id) + chat_channel = ChatChannel.find_by(id: chat_channel_id) + + return unless user && chat_channel + + service.call(user, chat_channel, message_html) + end + end +end diff --git a/app/models/message.rb b/app/models/message.rb index 0d2952307..4f95fa768 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -22,25 +22,7 @@ class Message < ApplicationRecord end def send_push - receiver_ids = chat_channel.chat_channel_memberships. - where.not(user_id: user.id).pluck(:user_id) - - PushNotificationSubscription.where(user_id: receiver_ids).find_each do |sub| - break if no_push_necessary?(sub) - - Webpush.payload_send( - endpoint: sub.endpoint, - message: ActionView::Base.full_sanitizer.sanitize(message_html), - p256dh: sub.p256dh_key, - auth: sub.auth_key, - ttl: 24 * 60 * 60, - vapid: { - subject: "https://dev.to", - public_key: ApplicationConfig["VAPID_PUBLIC_KEY"], - private_key: ApplicationConfig["VAPID_PRIVATE_KEY"] - }, - ) - end + Messages::SendPushJob.perform_later(user.id, chat_channel.id, message_html) end def direct_receiver @@ -96,11 +78,6 @@ class Message < ApplicationRecord errors.add(:base, "You are not a participant of this chat channel.") unless channel.has_member?(user) end - def no_push_necessary?(sub) - membership = sub.user.chat_channel_memberships.order("last_opened_at DESC").first - membership.last_opened_at > 40.seconds.ago - end - def rich_link_article(link) Article.find_by(slug: link["href"].split("/")[4].split("?")[0]) if link["href"].include?("//#{ApplicationConfig['APP_DOMAIN']}/") && link["href"].split("/")[4] end diff --git a/app/services/messages/send_push.rb b/app/services/messages/send_push.rb new file mode 100644 index 000000000..d4eddd3fb --- /dev/null +++ b/app/services/messages/send_push.rb @@ -0,0 +1,44 @@ +module Messages + class SendPush + def initialize(user, chat_channel, message_html) + @user = user + @chat_channel = chat_channel + @message_html = message_html + end + + def self.call(*args) + new(*args).call + end + + def call + receiver_ids = chat_channel.chat_channel_memberships. + where.not(user_id: user.id).pluck(:user_id) + + PushNotificationSubscription.where(user_id: receiver_ids).find_each do |sub| + break if no_push_necessary?(sub) + + Webpush.payload_send( + endpoint: sub.endpoint, + message: ActionView::Base.full_sanitizer.sanitize(message_html), + p256dh: sub.p256dh_key, + auth: sub.auth_key, + ttl: 24 * 60 * 60, + vapid: { + subject: "https://dev.to", + public_key: ApplicationConfig["VAPID_PUBLIC_KEY"], + private_key: ApplicationConfig["VAPID_PRIVATE_KEY"] + }, + ) + end + end + + private + + attr_reader :user, :chat_channel, :message_html + + def no_push_necessary?(sub) + membership = sub.user.chat_channel_memberships.order("last_opened_at DESC").first + membership.last_opened_at > 40.seconds.ago + end + end +end diff --git a/spec/jobs/messages/send_push_job_spec.rb b/spec/jobs/messages/send_push_job_spec.rb new file mode 100644 index 000000000..b4ec9ce0e --- /dev/null +++ b/spec/jobs/messages/send_push_job_spec.rb @@ -0,0 +1,49 @@ +require "rails_helper" + +RSpec.describe Messages::SendPushJob, type: :job do + include_examples "#enqueues_job", "messages_send_push", 456, 789, "