Fixes #3802 - Job scheduling respects time zone

This commit is contained in:
Mantas 2021-10-12 12:06:55 +03:00 committed by Thorsten Eckel
parent 3f48c222b5
commit e26d3ecfd3
4 changed files with 87 additions and 9 deletions

View file

@ -81,7 +81,7 @@ job.run(true)
end
def in_timeplan?(time = Time.zone.now)
Job::TimeplanCalculation.new(timeplan).contains?(time)
timeplan_calculation.contains?(time)
end
def matching_count
@ -89,6 +89,8 @@ job.run(true)
ticket_count || 0
end
private
def next_run_at_calculate(time = Time.zone.now)
return nil if !active
@ -96,11 +98,9 @@ job.run(true)
time += 10.minutes
end
Job::TimeplanCalculation.new(timeplan).next_at(time)
timeplan_calculation.next_at(time)
end
private
def updated_matching
self.matching = matching_count
end
@ -184,4 +184,10 @@ job.run(true)
end
end
end
def timeplan_calculation
timezone = Setting.get('timezone_default').presence || 'UTC'
Job::TimeplanCalculation.new(timeplan, timezone)
end
end

View file

@ -13,24 +13,33 @@ class Job::TimeplanCalculation
attr_reader :timeplan
def initialize(timeplan)
def initialize(timeplan, timezone)
@timeplan = timeplan.deep_transform_keys(&:to_s)
@timezone = timezone
end
def contains?(time)
return false if !valid?
day?(time) && hour?(time) && minute?(time)
time_in_zone = ensure_matching_time(time)
day?(time_in_zone) && hour?(time_in_zone) && minute?(time_in_zone)
end
def next_at(time)
return nil if !valid?
next_run_at_same_day(time) || next_run_at_coming_week(time)
time_in_zone = ensure_matching_time(time)
next_run_at_same_day(time_in_zone) || next_run_at_coming_week(time_in_zone)
end
private
def ensure_matching_time(time)
time.in_time_zone @timezone
end
def valid?
timeplan.key?('days') && timeplan.key?('hours') && timeplan.key?('minutes')
end

View file

@ -3,7 +3,9 @@
require 'rails_helper'
RSpec.describe Job::TimeplanCalculation do
subject(:instance) { described_class.new(timeplan) }
subject(:instance) { described_class.new(timeplan, timezone) }
let(:timezone) { nil }
describe '#contains?' do
context 'without a valid timeplan' do
@ -55,9 +57,17 @@ RSpec.describe Job::TimeplanCalculation do
it { is_expected.not_to be_contains(Time.zone.parse('2020-12-22 9:20')) }
it { is_expected.not_to be_contains(Time.zone.parse('2020-12-20 9:20')) }
end
context 'with monday 09:00 and time zone' do
let(:timeplan) { { 'days' => { 'Mon' => true }, 'hours' => { '1' => true }, 'minutes' => { '0' => true } } }
let(:timezone) { 'Europe/Vilnius' }
it { is_expected.to be_contains(Time.use_zone('Europe/Vilnius') { Time.zone.parse('2020-12-21 01:00') }) }
it { is_expected.to be_contains(Time.zone.parse('2020-12-20 23:00')) }
end
end
describe 'next_at?' do
describe '#next_at' do
context 'without a valid timeplan' do
let(:timeplan) { {} }
@ -125,6 +135,25 @@ RSpec.describe Job::TimeplanCalculation do
it { expect(instance.next_at(Time.zone.parse('2020-12-22 9:20'))).to eq(Time.zone.parse('2020-12-28 09:10')) }
it { expect(instance.next_at(Time.zone.parse('2020-12-20 9:20'))).to eq(Time.zone.parse('2020-12-21 09:10')) }
end
context 'with monday 09:00 and time zone' do
let(:timezone) { 'Europe/Vilnius' }
let(:timeplan) { { 'days' => { 'Mon' => true }, 'hours' => { '1' => true }, 'minutes' => { '0' => true } } }
it 'calculates time respecting time zone' do
from = Time.use_zone('Europe/Vilnius') { Time.zone.parse('2020-12-21 01:15') }
to = Time.use_zone('Europe/Vilnius') { Time.zone.parse('2020-12-28 01:00') }
expect(instance.next_at(from)).to eq(to)
end
it 'calculates time converting to time zone' do
from = Time.zone.parse('2020-12-20 23:10')
to = Time.use_zone('Europe/Vilnius') { Time.zone.parse('2020-12-28 01:00') }
expect(instance.next_at(from)).to eq(to)
end
end
end
describe 'legacy tests moved from Job model' do

View file

@ -345,6 +345,22 @@ RSpec.describe Job, type: :model do
end
end
end
describe '#in_timeplan?' do
before do
job.timeplan = { days: { Mon: true }, hours: { 0 => true }, minutes: { 0 => true } }
end
it 'checks in selected time zone' do
Setting.set 'timezone_default', 'Europe/Vilnius'
expect(job).to be_in_timeplan Time.zone.parse('2020-12-27 22:00')
end
it 'checks in UTC' do
expect(job).to be_in_timeplan Time.zone.parse('2020-12-28 00:00')
end
end
end
describe 'Attributes:' do
@ -451,6 +467,24 @@ RSpec.describe Job, type: :model do
end
end
end
context 'when updating #next_run_at' do
before do
travel_to Time.zone.parse('2020-12-27 00:00')
job.timeplan = { days: { Mon: true }, hours: { 0 => true }, minutes: { 0 => true } }
end
it 'sets #next_run_at time in selected time zone' do
Setting.set 'timezone_default', 'Europe/Vilnius'
expect { job.save }.to change(job, :next_run_at).to(Time.zone.parse('2020-12-27 22:00'))
end
it 'sets #next_run_at time in UTC' do
expect { job.save }.to change(job, :next_run_at).to(Time.zone.parse('2020-12-28 00:00'))
end
end
end
describe '#perform' do