Reputation: 48453
I have a mailer that send emails to company's clients about new products. The emails are sent out to thousands email addresses every day. Here's the code I use for it:
CRON job schedule:
every 1.day, at: local('7:00am') do
rake "mailer:daily_product_mailer", environment: 'production'
end
rake task:
namespace :mailer do desc "Daily product mailer"
task :daily_product_mailer => [:environment] do
DailyProductMailerJob.perform_later
end
end
Job task:
class DailyProductMailerJob < ApplicationJob
def perform
... preparing data...
DailyProductMailer.send_products.deliver_now
end
end
Mailer:
class DailyProductMailer < ApplicationMailer
...
def send_products
...
clients.each do |client|
@email = all_emails_str(client)
yield client, nil; next if @email.blank?
begin
@token = unsubscribe_token
Retryable.retryable( tries: 3, sleep: 30, on: [Net::OpenTimeout, Net::SMTPAuthenticationError, Net::SMTPServerBusy]) do
mail(to: @email, subject: "subject", from: [email protected]).deliver
end
yield client, @token
rescue Net::SMTPSyntaxError => e
error_msg = "Product mailer sending failed on #{Time.now} with: #{e.message}. e.inspect: #{e.inspect}"
InfonMailer.test_msg('[email protected]', 'Product Mailer - error', error_msg).deliver_now
logger.warn error_msg
yield carrier, @token
next
end
end
end
...
end
What happens here is that every morning is run a rake task (in the background) that calls a method that picks all clients from my database and sends out emails about the latest products.
Since a few days ago, I experience a problem when sending emails to certain email addresses fails, which causes significant performance issues of the whole server - everything in the Rails app is super slow, so I need to log in to the AWS EC2 instance, kill the Sidekiq process, then start it again. And next day the same procedure...
I am trying to identify the problem and I thought that the issue is here:
Retryable.retryable( tries: 3, sleep: 30, on: [Net::OpenTimeout, Net::SMTPAuthenticationError, Net::SMTPServerBusy]) do
mail(to: @email, subject: "subject", from: [email protected]).deliver
end
This block should try to execute the job that has failed up to 3 times - so I tried to remove it, but it didn't help - the job still stays stuck somewhere (and keeps slowing down the server).
What is the reason of Sidekiq blocking the server here? Is there a way to set Sidekiq to continue sending out emails to the new client email addresses if in the previous iteration occurred any error?
Upvotes: 0
Views: 943
Reputation: 3811
base on the document : https://github.com/mperham/sidekiq/wiki/Error-Handling
if the job failed then it will be retried 25 times (about 21 days) so i guess you put a-lot-of failed jobs every day then the retry queues was the cause of your server be slow.
so I tried to remove it
how did you try to remove it when you didn't log job_id ?
base on document : https://github.com/mperham/sidekiq/wiki/API
i think you can try selecting all jobs of a certain type and deleting them from the retry queue :
query = Sidekiq::RetrySet.new
query.select do |job|
job.klass == 'Sidekiq::Extensions::DelayedClass' &&
# For Sidekiq::Extensions (e.g., Foo.delay.bar(*args)),
# the context is serialized to YAML, and must
# be deserialized to get to the original args
((klass, method, args) = YAML.load(job.args[0])) &&
klass == User &&
method == :setup_new_subscriber
end.map(&:delete)
# a better approach using 6.0's `scan` to pre-filter
query.scan("setup_new_subscriber").select do |job|
job.klass == 'Sidekiq::Extensions::DelayedClass' &&
# For Sidekiq::Extensions (e.g., Foo.delay.bar(*args)),
# the context is serialized to YAML, and must
# be deserialized to get to the original args
((klass, method, args) = YAML.load(job.args[0])) &&
klass == User &&
method == :setup_new_subscriber
end.map(&:delete)
Upvotes: 0