-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ActiveJob perform_now no longer returns result of perform #38040
Comments
Oops, too quick on the submit. |
Some additional information and another related problem introduced by #37950. This line: 9eb4b4e#diff-141fdcf8e028bfeca079b4ebb5cb00a3R43 always returns class StatsLoggedJob < ActiveJob::Base
around_perform :log_results
def log_results
result = yield
FakeStatsLogger.log_stats({ stats_entry: result })
end
# ... [snip]
end |
Here is an updated version of the above reproduction script which shows both of the described issues:
activejob_returnval.rb # frozen_string_literal: true
require "bundler/inline"
gemfile(false) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
if ENV['RAILS_MASTER'] == "1"
gem "rails", github: "rails/rails"
else
gem "rails", "6.0.0"
end
end
require "active_job"
require "minitest/autorun"
class User
attr_accessor :id
def initialize(id)
@id = id
end
def self.all
(1..10).collect {|i| User.new(i)}
end
def has_warning?
self.id.even?
end
def send_warning
# Send a notification
end
end
class FakeStatsLogger
cattr_accessor :logs
def self.log_stats(value)
self.logs ||= []
self.logs << value
end
end
class BuggyJob < ActiveJob::Base
around_perform :log_results
def log_results
result = yield
FakeStatsLogger.log_stats({ stats_entry: result })
end
def perform
user_ids_with_warnings = []
User.all.each do |user|
if user.has_warning?
user.send_warning
user_ids_with_warnings << user.id
end
end
user_ids_with_warnings
end
end
class BuggyJobTest < ActiveJob::TestCase
def test_return_value_returns_perform_result
result = BuggyJob.perform_now
assert_equal [2,4,6,8,10], result
end
def test_around_perform_yield_returns_perform_result
result = BuggyJob.perform_now
assert_equal ({ stats_entry: [2,4,6,8,10] }), FakeStatsLogger.logs.last
end
end |
- ### Problem In bbfab0b33ab I introduced a change which outputs a deprecation whenever a class inherits from ActiveJob::Base. This has the negative effect to trigger a massive amount of deprecation at boot time especially if your app is eagerloaded (like it's usually the case on CI). Another issue with this approach was that the deprecation will be output no matter if a job define a `after_perform` callbacks i.e. ```ruby class MyJob < AJ::Base before_enqueue { throw(:abort) } end # This shouldn't trigger a deprecation since no after callbacks are defined # The change in 6.2 will be already safe for the app. ``` ### Solution Trigger the deprecation only when a job is abort (during enqueuing or performing) AND a `after_perform` callback is defined on the job.
I'll let @eileencodes make the final call but from what I could see in the documentation we never documented the return value of Is the BuggyJob sample you gave above representative of the actual failing job at GitHub? Otherwise if the job is just collecting the user ids in memory without either logging them or putting them in a Redis somewhere, it seems like quite the edge case to me. |
I think my change introduced a regression. It is a documented feature in AS::Callbacks rails/activesupport/lib/active_support/callbacks.rb Lines 650 to 651 in 1421ad5
around_perform { |, _block| result = block.call } that result would be whatever perform returned
|
Recently, ActiveJob's
.perform_now
method was updated in #37950 to return a boolean value indicating success or failure. Prior to the change,.perform_now
returned the result of.run_callbacks
, which in turn returned the result ofperform(*arguments)
.See: 9eb4b4e#diff-141fdcf8e028bfeca079b4ebb5cb00a3R41
It looks like the change was made to support improvements to deprecation warnings. Unfortunately it is causing problems at GitHub as we have quite a few tests (and a small number of methods in production) that rely on
.perform_now
returning the result of.perform
. It also seems pretty likely that dependence on the previous return value isn't unique to GitHub.The following reproduction script can be used to run an example using Rails 6.0 and 6.1
$ ruby activejob_returnval.rb && RAILS_MASTER=1 ruby activejob_returnval.rb
The text was updated successfully, but these errors were encountered: