Reputation: 34934
I need to create a User and send an email upon registration:
class User < ActiveRecord::Base
after_commit :send_email, on: :create # I believe it's better than after_create
# after_create :send_email, on: :create
class << self
def create_with_some_params(params)
#....
user.transaction do
if user.save && some_condition
user.category = category
raise ActiveRecord::Rollback unless user.category.persisted?
end
end
rescue => e
logger.error e.message
ensure
[user, some_data]
end
end
end
send_email(....)
#.....
end
end
At first I used after_create
to send an email, sending email was being performed within transaction. And pretty often a timeout occurred. So I started using after_commit
because it's called after the transaction and thus the timeout won't happen due to email being slowly.
So in this case with user.transaction do
, should I use after_commit
instead of after_create
to avoid transaction timeouts?
Upvotes: 1
Views: 999
Reputation: 5598
I prefer after_commit
in these scenarios because it does ensure that the entire transaction is done and committed to the DB before it 'acts'.
However, one thing you can do to help with the email slowness is add something like Sidekiq or DelayedJob (background processing) to improve app performance, especially Rails' notoriously slow mailers.
We've been using Sidekiq at work for a couple years and it's been a godsend as our app is a content delivery system!
MyMailer.delay.send_some_email(stuff) # this is how we can asynchronously send an email with Sidekiq
Using a background processor would eliminate the transaction timeouts should you either (a) want to stick with after_create
or (b) just want to speed up mailers :)!
Upvotes: 1