BigBinary Blog

We write about Ruby on Rails, React.js, React Native, remote work, open source, engineering and design.

Rails 6 adds support to persist timezones of Active Job

This blog is part of our Rails 6 series.

Rails 6.0 was recently released.

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.

Before:

Before Rails 6, we had to pass timezone explicitly to the perform method of the job as shown below.

1timezone = "Eastern Time (US & Canada)"
2
3AmazonSaleJob.perform_later(Time.now, timezone)
4
5class AmazonSaleJob < ApplicationJob
6  queue_as :default
7
8  def perform(time, timezone)
9
10    time = time.in_time_zone(timezone)
11    sale_start_time = localtime(2020, 12, 24)
12
13    if time >= sale_start_time
14      puts "Sale has started!"
15      #Send an email stating Sale has started
16    else
17      sale_starts_in = (sale_start_time - time).div(3600)
18      puts "Hang on! Sale will start in #{sale_starts_in} hours"
19      #Send an email stating sales starts in sale_starts_in hours
20     end
21  end
22
23  private
24
25    def localtime(*args)
26      Time.zone ? Time.zone.local(*args) : Time.utc(*args)
27    end
28end
29

After:

After the changes in Rails 6, passing timezone to Job is now taken care of by Rails.

1timezone = "Eastern Time (US & Canada)"
2
3Time.use_zone(timezone) do
4  AmazonSaleJob.perform_later(Time.zone.now)
5end
6
7class AmazonSaleJob < ApplicationJob
8  queue_as :default
9
10  def perform(time)
11    sale_start_time = localtime(2020, 12, 24)
12
13    if time >= sale_start_time
14      puts "Sale has started!"
15      #Send an email stating Sale has started
16    else
17      sale_starts_in = (sale_start_time - time).div(3600)
18      puts "Hang on! Sale will start in #{sale_starts_in} hours"
19      #Send an email stating sales starts in sale_starts_in hours
20     end
21   end
22
23  private
24
25    def localtime(*args)
26      Time.zone ? Time.zone.local(*args) : Time.utc(*args)
27    end
28end
29

Rails 6 also propagates timezone to all the subsequent nested jobs.

Chetan Gawai in Rails 6
September 1, 2020
Share

Subscribe to our newsletter