-
Notifications
You must be signed in to change notification settings - Fork 25.4k
(#34659) - Add Timezone Configuration to Watcher #117033
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(#34659) - Add Timezone Configuration to Watcher #117033
Conversation
Documentation preview: |
Pinging @elastic/es-docs (Team:Docs) |
Pinging @elastic/es-data-management (Team:Data Management) |
The algorithm depends on some quirks of calendar but LocalDateTime correctly ignores DST during calculations so this uses a LocalDateTime with a wrapper to emulate some of Calendar's behaviours that the Cron algorithm depends on
e0ceb34
to
e8c44bf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I left a couple of minor doc comments and a question about breaking BWC with existing watches.
These occur when the clock moves forward, such as when daylight savings time starts | ||
and cause certain hours or minutes to be skipped. If your watch is scheduled to run | ||
during a gap transition, the watch is executed at the same time as before the transition. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify if this also happens when the clock moves forward due to manual setting (e.g., if someone manually sets it 2 hours forward because it was incorrect)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No if someone (or NTP) moves the clock past a watch execution time, it will skip that execution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, what I meant was, could you add that clarification to the docs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh right sure thing :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change pushed
happen at 1:30AM (GMT+1). | ||
|
||
==== Overlap Transitions | ||
These occur when the clock moves backward, such as when daylight savings time ends |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here about clarification for manual backward moves
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case it would re-execute the watch when it hits the target time again
public static final int MAX_YEAR = Calendar.getInstance(UTC, Locale.ROOT).get(Calendar.YEAR) + 100; | ||
// Restricted to 50 years as the tzdb only has correct DST transition information for countries using a lunar calendar | ||
// for the next ~60 years | ||
public static final int MAX_YEAR = Calendar.getInstance(UTC, Locale.ROOT).get(Calendar.YEAR) + 50; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random question, but let's assume someone already had a cron expression in their Watcher configuration that was using a date 75 years in the future. Would changing this cause that Watch to fail now that it's a lower restriction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No this is simply used as a short circuit for next runtime algorithm to stop it trying to calculate too far into the future. We recalculate next runtime on each watcher service start so eventually it would come in range and have its execution time calculated.
What could happen is if they had a watch 51 years in the future and never restarted the ES node for 50 years, then the watch would never run, but I think that cause should be uncommon enough that the protection this provides against long-running next runtime calculations / guarding against DST data being wrong is worth it.
…ictable watch execution
…tcher-timezone-support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, left one more comment about a tiny typo. Thanks Luke, this has been requested for quite a while, so it's nice to be able to get it in!
Co-authored-by: Lee Hinman <[email protected]>
@dakrone Yeah it was a bit of a mission and I would have liked time to completely rewrite the Cron class but I think this is a pragmatic solution in the end :-) I'll merge this Monday as I don't want to invoke the curse of the Friday evening merge. |
💚 Backport successful
|
* Add timezone support to Cron objects * Add timezone support to CronnableSchedule * XContent change to support parsing and display of TimeZone fields on schedules * Case insensitive timezone parsing * Doc changes * YAML REST tests * Equals, toString and HashCode now include timezone * Additional random testing for DST transitions * Migrate Cron class to use wrapped LocalDateTime The algorithm depends on some quirks of calendar but LocalDateTime correctly ignores DST during calculations so this uses a LocalDateTime with a wrapper to emulate some of Calendar's behaviours that the Cron algorithm depends on * Additional documentation to explain discontinuity event behaviour * Remove redundant conversions from ZoneId to TimeZone following move to LocalDateTime * Add documentation warning that manual clock changes will cause unpredictable watch execution * Update docs/reference/watcher/trigger/schedule.asciidoc Co-authored-by: Lee Hinman <[email protected]> --------- Co-authored-by: Lee Hinman <[email protected]>
* Add timezone support to Cron objects * Add timezone support to CronnableSchedule * XContent change to support parsing and display of TimeZone fields on schedules * Case insensitive timezone parsing * Doc changes * YAML REST tests * Equals, toString and HashCode now include timezone * Additional random testing for DST transitions * Migrate Cron class to use wrapped LocalDateTime The algorithm depends on some quirks of calendar but LocalDateTime correctly ignores DST during calculations so this uses a LocalDateTime with a wrapper to emulate some of Calendar's behaviours that the Cron algorithm depends on * Additional documentation to explain discontinuity event behaviour * Remove redundant conversions from ZoneId to TimeZone following move to LocalDateTime * Add documentation warning that manual clock changes will cause unpredictable watch execution * Update docs/reference/watcher/trigger/schedule.asciidoc --------- Co-authored-by: Lee Hinman <[email protected]>
* Add timezone support to Cron objects * Add timezone support to CronnableSchedule * XContent change to support parsing and display of TimeZone fields on schedules * Case insensitive timezone parsing * Doc changes * YAML REST tests * Equals, toString and HashCode now include timezone * Additional random testing for DST transitions * Migrate Cron class to use wrapped LocalDateTime The algorithm depends on some quirks of calendar but LocalDateTime correctly ignores DST during calculations so this uses a LocalDateTime with a wrapper to emulate some of Calendar's behaviours that the Cron algorithm depends on * Additional documentation to explain discontinuity event behaviour * Remove redundant conversions from ZoneId to TimeZone following move to LocalDateTime * Add documentation warning that manual clock changes will cause unpredictable watch execution * Update docs/reference/watcher/trigger/schedule.asciidoc Co-authored-by: Lee Hinman <[email protected]> --------- Co-authored-by: Lee Hinman <[email protected]>
This adds support for specifying a timezone as part of a Watcher schedule. It includes documentation, serialization and parsing changes.
Elements Of Note
Handling of DST discontinuity
Having time zones means we need to deal with transitions to and from DST where a given time may be skipped or duplicated during a transition (Known as a Discontinuity). See docs and
CronTimezoneTests
for expected behaviour during these events.Changes to Cron Class'
getNextValidTimeAfter(...)
MethodTo support timezones, it was necessary to update this method to be timezone aware. Unfortunately the underlying clock object (A legacy
Calendar
instance) behaved in an undesirable way during DST Discontinuity events causing watches to be skipped and duplicated.A rewrite to
LocalDateTime
resolved such issues due to it's better handling of Local -> UTC time conversion and discontinuities however the getNextValidTimeAfter(...) algorithm depended heavily on quirks of theCalendar
object such as being able to set the current hour to24
causing the day to roll over and the hour to be set to0
.A full rewrite of this method would risk introducing too many possible behaviour changes so instead I opted to wrap
LocalDateTime
and emulate the quirks ofCalendar
while retaining the better local date time -> UTC conversions, reducing the risk of unexpected behaviour changes and reducing implementation time at the expense of some additional code complexity.Fixes #34659