Refactors ActiveJob to SidekiqWorker: Follows::SendEmailNotificationWorker (#5322) [deploy]

* Refactors ActiveJob to SidekiqWorker: Follows::SendEmailNotificationWorker
* improves naming of User#receives_follower_email_notifications?
* adjust expect count for spec SendEmailNotificationWorker
This commit is contained in:
Lud 2020-01-02 19:35:09 +01:00 committed by Molly Struve
parent 783d43b737
commit df042d6b0b
8 changed files with 105 additions and 5 deletions

View file

@ -1,3 +1,4 @@
# @TODO: to be removed in favor of `app/workers/follows/send_email_notification_worker.rb`
module Follows
class SendEmailNotificationJob < ApplicationJob
queue_as :send_follow_email_notification

View file

@ -1,4 +1,8 @@
class NotifyMailer < ApplicationMailer
SUBJECTS = {
new_follower_email: "just followed you on dev.to".freeze
}.freeze
def new_reply_email(comment)
@user = comment.parent_user
return if RateLimitChecker.new.limit_by_email_recipient_address(@user.email)
@ -15,7 +19,7 @@ class NotifyMailer < ApplicationMailer
@follower = follow.follower
@unsubscribe = generate_unsubscribe_token(@user.id, :email_follower_notifications)
mail(to: @user.email, subject: "#{@follower.name} just followed you on dev.to")
mail(to: @user.email, subject: "#{@follower.name} #{SUBJECTS[__method__]}")
end
def new_mention_email(mention)

View file

@ -46,7 +46,7 @@ class Follow < ApplicationRecord
def send_email_notification
return unless followable.class.name == "User" && followable.email?
Follows::SendEmailNotificationJob.perform_later(id)
Follows::SendEmailNotificationWorker.perform_async(id)
end
def modify_chat_channel_status

View file

@ -451,6 +451,11 @@ class User < ApplicationRecord
credits.unspent.size >= num_credits_needed
end
def receives_follower_email_notifications?
email.present? &&
email_follower_notifications
end
private
def index_id

View file

@ -0,0 +1,17 @@
module Follows
class SendEmailNotificationWorker
include Sidekiq::Worker
sidekiq_options queue: :mailers, retry: 10
def perform(follow_id, mailer = NotifyMailer.name)
follow = Follow.find_by(id: follow_id, followable_type: "User")
return unless follow&.followable.present? && follow.followable.receives_follower_email_notifications?
return if EmailMessage.where(user_id: follow.followable_id).
where("sent_at > ?", rand(15..35).hours.ago).
where("subject LIKE ?", "%#{NotifyMailer::SUBJECTS[:new_follower_email]}").exists?
mailer.constantize.new_follower_email(follow).deliver
end
end
end

View file

@ -26,10 +26,10 @@ RSpec.describe Follow, type: :model do
end.to have_enqueued_job(Follows::CreateChatChannelJob)
end
it "enqueues send notification job" do
it "enqueues send notification worker" do
expect do
described_class.create(follower: user, followable: user_2)
end.to have_enqueued_job(Follows::SendEmailNotificationJob)
end.to change(Follows::SendEmailNotificationWorker.jobs, :size).by(1)
end
end
@ -73,7 +73,7 @@ RSpec.describe Follow, type: :model do
it "sends an email notification" do
user_2.update_column(:email_follower_notifications, true)
expect do
perform_enqueued_jobs do
Sidekiq::Testing.inline! do
described_class.create!(follower: user, followable: user_2)
end
end.to change(EmailMessage, :count).by(1)

View file

@ -727,4 +727,21 @@ RSpec.describe User, type: :model do
expect(user.enough_credits?(1)).to be(true)
end
end
describe "#receives_follower_email_notifications?" do
it "returns false if user has no email" do
user.assign_attributes(email: nil)
expect(user.receives_follower_email_notifications?).to be(false)
end
it "returns false if user opted out from follower notifications" do
user.assign_attributes(email_follower_notifications: false)
expect(user.receives_follower_email_notifications?).to be(false)
end
it "returns true if user opted in from follower notifications and has an email" do
user.assign_attributes(email_follower_notifications: true)
expect(user.receives_follower_email_notifications?).to be(true)
end
end
end

View file

@ -0,0 +1,56 @@
require "rails_helper"
class MockMailer
def self.deliver; end
end
RSpec.describe Follows::SendEmailNotificationWorker, type: :worker do
subject(:worker) { described_class }
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
let_it_be(:follow) { create(:follow, follower: user, followable: user2) }
describe "#perform" do
before do
allow(NotifyMailer).to receive(:new_follower_email).and_return(MockMailer)
allow(MockMailer).to receive(:deliver)
worker.perform_async(follow_id)
end
context "with follow" do
let(:follow_id) { follow.id }
it "sends a new_follower_email" do
user2.update_column(:email_follower_notifications, true)
worker.drain
expect(MockMailer).to have_received(:deliver).once
end
it "doesn't send an email if user has disabled notifications" do
user2.update_column(:email_follower_notifications, false)
worker.drain
expect(MockMailer).not_to have_received(:deliver)
end
it "doesn't create an EmailMessage if it already exists" do
subject = "#{user.username} just followed you on dev.to"
EmailMessage.create!(user_id: user2.id, sent_at: Time.current, subject: subject)
worker.drain
expect(MockMailer).not_to have_received(:deliver)
end
end
context "without follow" do
let(:follow_id) { nil }
it "does not break" do
expect { worker.drain }.not_to raise_error
end
end
end
end