diff options
-rw-r--r-- | activejob/CHANGELOG.md | 8 | ||||
-rw-r--r-- | activejob/lib/active_job/base.rb | 2 | ||||
-rw-r--r-- | activejob/lib/active_job/core.rb | 7 | ||||
-rw-r--r-- | activejob/lib/active_job/timezones.rb | 13 | ||||
-rw-r--r-- | activejob/test/cases/job_serialization_test.rb | 7 | ||||
-rw-r--r-- | activejob/test/cases/timezones_test.rb | 24 | ||||
-rw-r--r-- | activejob/test/integration/queuing_test.rb | 16 | ||||
-rw-r--r-- | activejob/test/jobs/timezone_dependent_job.rb | 22 | ||||
-rw-r--r-- | activejob/test/support/integration/dummy_app_template.rb | 1 | ||||
-rw-r--r-- | activejob/test/support/integration/test_case_helpers.rb | 4 |
10 files changed, 103 insertions, 1 deletions
diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 097433c3d0..c6a3ad8ade 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,5 +1,13 @@ ## Rails 6.0.0.alpha (Unreleased) ## +* Add support for timezones to Active Job + + Record what was the current timezone in effect when the job was + enqueued and then restore when the job is executed in same way + that the current locale is recorded and restored. + + *Andrew White* + * Rails 6 requires Ruby 2.4.1 or newer. *Jeremy Daer* diff --git a/activejob/lib/active_job/base.rb b/activejob/lib/active_job/base.rb index 6194f89956..2b2a59e969 100644 --- a/activejob/lib/active_job/base.rb +++ b/activejob/lib/active_job/base.rb @@ -9,6 +9,7 @@ require "active_job/execution" require "active_job/callbacks" require "active_job/exceptions" require "active_job/logging" +require "active_job/timezones" require "active_job/translation" module ActiveJob #:nodoc: @@ -68,6 +69,7 @@ module ActiveJob #:nodoc: include Callbacks include Exceptions include Logging + include Timezones include Translation ActiveSupport.run_load_hooks(:active_job, self) diff --git a/activejob/lib/active_job/core.rb b/activejob/lib/active_job/core.rb index 879746fc01..da841ae45b 100644 --- a/activejob/lib/active_job/core.rb +++ b/activejob/lib/active_job/core.rb @@ -31,6 +31,9 @@ module ActiveJob # I18n.locale to be used during the job. attr_accessor :locale + + # Timezone to be used during the job. + attr_accessor :timezone end # These methods will be included into any Active Job object, adding @@ -87,7 +90,8 @@ module ActiveJob "priority" => priority, "arguments" => serialize_arguments(arguments), "executions" => executions, - "locale" => I18n.locale.to_s + "locale" => I18n.locale.to_s, + "timezone" => Time.zone.try(:name) } end @@ -125,6 +129,7 @@ module ActiveJob self.serialized_arguments = job_data["arguments"] self.executions = job_data["executions"] self.locale = job_data["locale"] || I18n.locale.to_s + self.timezone = job_data["timezone"] || Time.zone.try(:name) end private diff --git a/activejob/lib/active_job/timezones.rb b/activejob/lib/active_job/timezones.rb new file mode 100644 index 0000000000..83f459aea5 --- /dev/null +++ b/activejob/lib/active_job/timezones.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module ActiveJob + module Timezones #:nodoc: + extend ActiveSupport::Concern + + included do + around_perform do |job, block, _| + Time.use_zone(job.timezone, &block) + end + end + end +end diff --git a/activejob/test/cases/job_serialization_test.rb b/activejob/test/cases/job_serialization_test.rb index 440051c427..5c9994508e 100644 --- a/activejob/test/cases/job_serialization_test.rb +++ b/activejob/test/cases/job_serialization_test.rb @@ -54,4 +54,11 @@ class JobSerializationTest < ActiveSupport::TestCase job.provider_job_id = "some value set by adapter" assert_equal job.provider_job_id, job.serialize["provider_job_id"] end + + test "serialize stores the current timezone" do + Time.use_zone "Hawaii" do + job = HelloJob.new + assert_equal "Hawaii", job.serialize["timezone"] + end + end end diff --git a/activejob/test/cases/timezones_test.rb b/activejob/test/cases/timezones_test.rb new file mode 100644 index 0000000000..e2095b020d --- /dev/null +++ b/activejob/test/cases/timezones_test.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require "helper" +require "jobs/timezone_dependent_job" + +class TimezonesTest < ActiveSupport::TestCase + setup do + JobBuffer.clear + end + + test "it performs the job in the given timezone" do + job = TimezoneDependentJob.new("2018-01-01T00:00:00Z") + job.timezone = "London" + job.perform_now + + assert_equal "Happy New Year!", JobBuffer.last_value + + job = TimezoneDependentJob.new("2018-01-01T00:00:00Z") + job.timezone = "Eastern Time (US & Canada)" + job.perform_now + + assert_equal "Just 5 hours to go", JobBuffer.last_value + end +end diff --git a/activejob/test/integration/queuing_test.rb b/activejob/test/integration/queuing_test.rb index 32ef485c45..7a95d3d039 100644 --- a/activejob/test/integration/queuing_test.rb +++ b/activejob/test/integration/queuing_test.rb @@ -110,6 +110,22 @@ class QueuingTest < ActiveSupport::TestCase end end + test "current timezone is kept while running perform_later" do + skip if adapter_is?(:inline) + + begin + current_zone = Time.zone + Time.zone = "Hawaii" + + TestJob.perform_later @id + wait_for_jobs_to_finish_for(5.seconds) + assert job_executed + assert_equal "Hawaii", job_executed_in_timezone + ensure + Time.zone = current_zone + end + end + test "should run job with higher priority first" do skip unless adapter_is?(:delayed_job, :que) diff --git a/activejob/test/jobs/timezone_dependent_job.rb b/activejob/test/jobs/timezone_dependent_job.rb new file mode 100644 index 0000000000..41f473d533 --- /dev/null +++ b/activejob/test/jobs/timezone_dependent_job.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require_relative "../support/job_buffer" + +class TimezoneDependentJob < ActiveJob::Base + def perform(now) + now = now.in_time_zone + new_year = localtime(2018, 1, 1) + + if now >= new_year + JobBuffer.add("Happy New Year!") + else + JobBuffer.add("Just #{(new_year - now).div(3600)} hours to go") + end + end + + private + + def localtime(*args) + Time.zone ? Time.zone.local(*args) : Time.utc(*args) + end +end diff --git a/activejob/test/support/integration/dummy_app_template.rb b/activejob/test/support/integration/dummy_app_template.rb index 7ea78c3350..b56dd3e591 100644 --- a/activejob/test/support/integration/dummy_app_template.rb +++ b/activejob/test/support/integration/dummy_app_template.rb @@ -21,6 +21,7 @@ class TestJob < ActiveJob::Base File.open(Rails.root.join("tmp/\#{x}.new"), "wb+") do |f| f.write Marshal.dump({ "locale" => I18n.locale.to_s || "en", + "timezone" => Time.zone.try(:name) || "UTC", "executed_at" => Time.now.to_r }) end diff --git a/activejob/test/support/integration/test_case_helpers.rb b/activejob/test/support/integration/test_case_helpers.rb index f02a32a38e..3d9b265b66 100644 --- a/activejob/test/support/integration/test_case_helpers.rb +++ b/activejob/test/support/integration/test_case_helpers.rb @@ -62,4 +62,8 @@ module TestCaseHelpers def job_executed_in_locale(id = @id) job_data(id)["locale"] end + + def job_executed_in_timezone(id = @id) + job_data(id)["timezone"] + end end |