Skip to content

(#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

Merged
merged 14 commits into from
Nov 25, 2024

Conversation

lukewhiting
Copy link
Contributor

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(...) Method

To 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 the Calendar object such as being able to set the current hour to 24 causing the day to roll over and the hour to be set to 0.

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 of Calendar 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

Copy link
Contributor

Documentation preview:

@elasticsearchmachine elasticsearchmachine added Team:Data Management Meta label for data/management team Team:Docs Meta label for docs team labels Nov 19, 2024
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-docs (Team:Docs)

@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-data-management (Team:Data Management)

Copy link
Member

@dakrone dakrone left a 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.

Comment on lines +21 to +23
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.
Copy link
Member

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)

Copy link
Contributor Author

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

Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh right sure thing :-)

Copy link
Contributor Author

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
Copy link
Member

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

Copy link
Contributor Author

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;
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

@dakrone dakrone left a 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!

@lukewhiting
Copy link
Contributor Author

lukewhiting commented Nov 22, 2024

@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.

@lukewhiting lukewhiting merged commit 1d4c8d8 into elastic:main Nov 25, 2024
14 checks passed
@lukewhiting lukewhiting added the auto-backport Automatically create backport pull requests when merged label Nov 25, 2024
@elasticsearchmachine
Copy link
Collaborator

💚 Backport successful

Status Branch Result
8.x

lukewhiting added a commit to lukewhiting/elasticsearch that referenced this pull request Nov 25, 2024
* 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]>
@lukewhiting lukewhiting deleted the 34659-watcher-timezone-support branch November 25, 2024 09:55
@lukewhiting lukewhiting restored the 34659-watcher-timezone-support branch November 25, 2024 09:55
elasticsearchmachine pushed a commit that referenced this pull request Nov 25, 2024
* 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]>
@lukewhiting lukewhiting deleted the 34659-watcher-timezone-support branch November 27, 2024 10:32
alexey-ivanov-es pushed a commit to alexey-ivanov-es/elasticsearch that referenced this pull request Nov 28, 2024
* 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-backport Automatically create backport pull requests when merged :Data Management/Watcher >docs General docs changes >enhancement Team:Data Management Meta label for data/management team Team:Docs Meta label for docs team v8.18.0 v9.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Timezone Configuration to Watcher
3 participants