September 1, 2020
This blog is part of our Rails 6 series.
When a job is enqueued in Rails 6 using Active Job, the current timezone of a job is preserved and then this preserved timezone is restored when the job is finished executing.
Let's take an example of sale at Amazon.
Amazon would like to remind users across different timezones about its upcoming sale by sending an email. This task of sending a reminder would be processed as a background job.
<b>Before:</b>
Before Rails 6, we had to pass timezone explicitly to the perform
method of
the job as shown below.
timezone = "Eastern Time (US & Canada)"
AmazonSaleJob.perform_later(Time.now, timezone)
class AmazonSaleJob < ApplicationJob
queue_as :default
def perform(time, timezone)
time = time.in_time_zone(timezone)
sale_start_time = localtime(2020, 12, 24)
if time >= sale_start_time
puts "Sale has started!"
#Send an email stating Sale has started
else
sale_starts_in = (sale_start_time - time).div(3600)
puts "Hang on! Sale will start in #{sale_starts_in} hours"
#Send an email stating sales starts in sale_starts_in hours
end
end
private
def localtime(*args)
Time.zone ? Time.zone.local(*args) : Time.utc(*args)
end
end
<b>After:</b>
After the changes in Rails 6, passing timezone to Job is now taken care of by Rails.
timezone = "Eastern Time (US & Canada)"
Time.use_zone(timezone) do
AmazonSaleJob.perform_later(Time.zone.now)
end
class AmazonSaleJob < ApplicationJob
queue_as :default
def perform(time)
sale_start_time = localtime(2020, 12, 24)
if time >= sale_start_time
puts "Sale has started!"
#Send an email stating Sale has started
else
sale_starts_in = (sale_start_time - time).div(3600)
puts "Hang on! Sale will start in #{sale_starts_in} hours"
#Send an email stating sales starts in sale_starts_in hours
end
end
private
def localtime(*args)
Time.zone ? Time.zone.local(*args) : Time.utc(*args)
end
end
Rails 6 also propagates timezone to all the subsequent nested jobs.
If this blog was helpful, check out our full blog archive.