Thread safety with regard to time zone handling #220

Closed
knu opened this Issue Nov 11, 2016 · 11 comments

Projects

None yet

2 participants

@knu
knu commented Nov 11, 2016 edited

Rufus-scheduler introduced ZoTime in 3.1.0, and since then ENV['TZ'] may get modified in run time, where other threads may be creating Time objects or spawning child processes.

So, my question is, when do ZoTime#time and ZoTime#utc have a chance to be called? Is it only when a schedule is registered using a time zone in the cron line, or is there a chance to be re-evaluated when some event occurs?

@jmettraux
Owner

Hello,

as you guessed ZoTime#time is called upon registering a cron schedule.

It is also called upon a CronJob#next_time or a CronJob#previous_time.

ENV['TZ'] is consulted by cron jobs when there is no definite time zone in the cron string (upon creation and for #next_time and #previous_time. That might be a problem (maybe that's what prompted you to open this issue). One solution could be to keep track of the timezone at the point of creation of the CronJob instance.

I'd be glad to help once I know exactly what bothers you.

Best regards.

@knu
knu commented Nov 11, 2016

Thanks for the quick reply!

I have a system that persistently runs a scheduler built with rufus-scheduler, and the system dynamically adds or deletes schedules upon a request via API. Each schedule periodically invokes a specified job on a specified time/interval, and the process involves running an external command, making an HTTP request and accessing DB while executing jobs.

So, what I need here is make sure jobs are not affected by registration of new schedules.

@jmettraux jmettraux self-assigned this Nov 11, 2016
@jmettraux
Owner

Ah, I understand. Indeed, the calls to ZoTime#in_zone are problematic. I will study how to avoid using it. It's currently used in two places in ZoTime.

Thanks for reporting that. Please give me a few days.

@knu
knu commented Nov 11, 2016

Great. Thanks for taking the time! Actually I was about to start working on a PR, but before that I just wanted to know what you'd think about the idea of fixing it.

@jmettraux jmettraux removed their assignment Nov 11, 2016
@jmettraux
Owner

OK, got it. I'd be glad to have a PR from you.

@knu
knu commented Nov 11, 2016

After some investigation, I've found you need to add back the parser for TZ values. TZInfo or ActiveSupport::TimeZone can parse timezone representations like Asia/Tokyo or PST, but not JST-9. It is likely you could do that better. 😥

@jmettraux jmettraux self-assigned this Nov 11, 2016
@jmettraux
Owner

I will bring back the dependency on TZInfo and cook something based on it that doesn't touch ENV['TZ'].

Thanks again.

@jmettraux jmettraux added a commit that referenced this issue Nov 12, 2016
@jmettraux Explore TZInfo backed ZoTime for gh-220
Work in progress
fbd75ef
@jmettraux jmettraux added a commit that referenced this issue Nov 12, 2016
@jmettraux Store UTC seconds in ZoTime, gh-220
[ci skip]
473b530
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Drop ZoTime#time, gh-220
[ci skip]
0d13ea0
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Reorganize ZoTime spec, gh-220
[ci skip]
a373250
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Introduce %/Z for ZoTime#strftime, gh-220
[ci skip]
c58e9c4
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Default ZoTime to ENV['TZ'], gh-220
[ci skip]
5153857
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Delegate from ZoTime to its #to_time, gh-220
[ci skip]
8d93b38
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Move from .parse_to_time to ZoTime.make, gh-220
[ci skip]
625b9b1
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Tighten ZoTime.parse, gh-220
[ci skip]
40fe097
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Implement ZoTime#<=>, gh-220
[ci skip]
b231209
@jmettraux jmettraux added a commit that referenced this issue Nov 13, 2016
@jmettraux Move #monthdays from CronLine to ZoTime, gh-220
[ci skip]
de35fb4
@jmettraux jmettraux added a commit that referenced this issue Nov 14, 2016
@jmettraux Rework CronLine#next_time, gh-220
[ci skip]
0df80b8
@jmettraux jmettraux added a commit that referenced this issue Nov 14, 2016
@jmettraux Rework CronLine#previous_time, gh-220
[ci skip]
ff16616
@jmettraux jmettraux added a commit that referenced this issue Nov 14, 2016
@jmettraux Reorganize #[brute_]frequency specs, gh-220
[ci skip]
91a09bb
@jmettraux
Owner

It's taking its time but it's starting to look good.

@jmettraux jmettraux added a commit that referenced this issue Nov 15, 2016
@jmettraux Cache ZoTime#to_time result into @time, gh-220
[ci skip]
9327bc0
@jmettraux jmettraux added a commit that referenced this issue Nov 15, 2016
@jmettraux Store timezone instance in CronLine, gh-220
[ci skip]

Still, the "shortest delta" specs are 3 times slower than they were before this gh-220 rework. Digging...
9b172d7
@jmettraux jmettraux added a commit that referenced this issue Nov 17, 2016
@jmettraux Adapt CronLine spec to explict @timezone, gh-220
Beforehand, the local timezone in the CronLine was stored as `nil`, from gh-220 on, it is stored as a TZInfo::Timezone (like CronLine with non-local timezones).
87c3588
@jmettraux jmettraux added a commit that referenced this issue Nov 17, 2016
@jmettraux Complete adaptation of cronline_spec.rb to gh-220
Though it's running in ~19.5 seconds vs ~7.0 seconds (pre gh-220) on Ruby 2.2.5p319.

Make it run, make it fast.
7e77fae
@jmettraux jmettraux added a commit that referenced this issue Nov 18, 2016
@jmettraux Use ZoTime within jobs, gh-220
[ci skip]
d5c0cc6
@jmettraux jmettraux added a commit that referenced this issue Nov 18, 2016
@jmettraux Adapt at spec to gh-220
[ci skip]
4be4b71
@jmettraux jmettraux added a commit that referenced this issue Nov 18, 2016
@jmettraux Rework @first_at computation for gh-220
[ci skip]
0666126
@jmettraux jmettraux added a commit that referenced this issue Nov 21, 2016
@jmettraux Add ZoTime#utc_offset, gh-220 9f0176e
@jmettraux jmettraux added a commit that referenced this issue Nov 21, 2016
@jmettraux Introduce ZoTime / Time #to_debug_s, gh-220
Focus on utc_offset instead of zone name (which various wildly between 1.8, 2.x or JRuby)
a745998
@jmettraux
Owner

Hello, apart from a slight problem with JRuby, this transition is done.

If you have the time, please have a look 781c009...184bd6a

Your comments are welcome.

Many thanks for making me realize the problem behind my ENV['TZ'] approach.

I will close this issue soon. I'll release this as part of the upcoming 3.3.0

@knu
knu commented Nov 27, 2016

Wow, this must have been a tough work! Thanks!

I've deployed the current master to my personal installation and so far it's been working fine.

@jmettraux
Owner

Thanks, closing for now !

@jmettraux jmettraux closed this Nov 27, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment