Skip to content

Delay every data update poll by a random amount, drawn afresh each time - #182

Draft
jwrosewell wants to merge 3 commits into
release/4.5.12from
fix/data-update-random-polling
Draft

jwrosewell wants to merge 3 commits into
release/4.5.12from
fix/data-update-random-polling

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Closes #161.

Problem

randomisation hashed Instant::now().elapsed(), the time since an instant made a moment before, with the thread's id, through DefaultHasher, whose keys are fixed (pipeline-engines/src/data_update_service.rs lines 295 to 307). The elapsed time is a few nanoseconds on every call, so every process drew from the same few values, and 200 draws of a delay of up to 600 seconds gave two different values. run_due_polls scheduled every poll after the first at the polling interval alone (lines 512 to 527). Instances started together therefore polled the Distributor together, every time. The specification adds a random time to every interval (data-updates.md lines 354 to 356), as .NET and Java do. #161 has the details.

Change

  • The delay is drawn from a hasher made by a new RandomState, whose keys the standard library draws from the operating system, and seeded with the system time, so it differs between calls and between processes without a random number generator dependency.
  • Every poll waits the polling interval plus a new delay, through the same function the first poll uses. poll_interval and randomisation take no service, so the scheduler can call them.

How it was verified

New unit tests in pipeline-engines/src/data_update_service.rs:

  • the_first_poll_is_delayed_at_random draws 200 delays of up to 600 seconds and checks more than 100 differ. About 170 differ when the draws are random.
  • each_later_poll_adds_a_random_delay runs five due polls with a 1,000 second interval and a 1,000 second maximum delay, and checks at least one is next due more than a second after the interval. All five would land under two seconds once in about 3 * 10^13 runs.

Before the change, on a branch holding only the new tests, both fail, the_first_poll_is_delayed_at_random with 2 different delays in 200: {114, 592} and each_later_poll_adds_a_random_delay with no poll after the first added a delay. After it, both pass, and the first prints 180 different delays in 200.

Locally on Windows, with all seven fixes of this sweep merged together (#175, #178, #182, #184, #194, #195 and #196), cargo test --no-fail-fast -p fiftyone-pipeline-engines -p fiftyone-device-detection-onpremise -p fiftyone-ip-intelligence-onpremise -p fiftyone-device-detection -p fiftyone-ip-intelligence -- --nocapture, with 51DEGREES_DD_PATH naming the Lite Hash file, Enterprise-HashV41.hash beside it, and 51DEGREES_IPI_PATH naming the ASN file, 51Degrees-LiteV41.ipi beside it, gives 130 passed, 0 failed and 2 ignored across 24 test binaries. With the fixes merged, cargo doc --workspace --no-deps with RUSTDOCFLAGS="-D warnings" passes, and rustfmt --check passes on every file the seven fixes change. cargo clippy --workspace --all-targets -- -D warnings on the merged fixes has not run yet. The Pull Request workflow, which builds and tests each pull request on every platform, is waiting for approval to run.

Behaviour that changes

Polls are spread across the configured maximum randomisation, the first and every later one, so instances started together drift apart. A poll after the first now comes between the polling interval and the polling interval plus the maximum randomisation after the one before, where before it came after the polling interval exactly.

What remains

Nothing in this change.

The delay hashed the time elapsed since an instant made a moment before,
which is close to zero on every call, with the thread's id, so every
process drew from a handful of values and instances started together
polled together. Polls after the first added no delay at all. The delay is
now drawn from a randomly keyed hasher and added to every poll, as the
specification says.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant