Class: RuboCop::Cop::DevDoc::Rails::NoDeliverLaterInTransaction
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::DevDoc::Rails::NoDeliverLaterInTransaction
- Defined in:
- lib/rubocop/cop/dev_doc/rails/no_deliver_later_in_transaction.rb
Overview
Avoid deliver_later and perform_later inside a transaction block.
Rationale
Do not use perform_later or deliver_later inside a transaction
block because there is a possibility that the job will use stale data,
as the transaction has not yet completed (not yet committed changes
to the database).
❌
organization.transaction do
if organization.save
# This mailer may receive the organization with stale data
# (data before `save()`)
OrganizationMailer.with(organization: organization).deliver_later
end
end
✔️
organization.transaction do
save_succeeded = organization.save
end
if save_succeeded
OrganizationMailer.with(organization: organization).deliver_later
end
Configurable blocklist for library wrappers
Some libraries call perform_later / deliver_later behind the
scenes. Configure KnownAsyncWrappers to flag those methods too.
Common Devise methods are included by default. This is a partial
mitigation — reviewers must still catch unknown wrappers not in the
list.
Constant Summary collapse
- MSG =
'`%<method>s` inside a `transaction` block may use stale data. Move it outside the transaction.'.freeze
- CORE_METHODS =
%i[deliver_later perform_later].freeze
Instance Method Summary collapse
Instance Method Details
#on_send(node) ⇒ Object
60 61 62 63 64 65 |
# File 'lib/rubocop/cop/dev_doc/rails/no_deliver_later_in_transaction.rb', line 60 def on_send(node) return unless inside_transaction?(node) return unless tracked_method?(node.method_name) add_offense(node.loc.selector, message: format(MSG, method: node.method_name)) end |