Skip to content

fix: isolate deterministic workflow clock values - #512

Merged
rmcdaniel merged 2 commits into
mainfrom
fix/deterministic-clock-copy
Sep 12, 2026
Merged

fix: isolate deterministic workflow clock values#512
rmcdaniel merged 2 commits into
mainfrom
fix/deterministic-clock-copy

Conversation

@rmcdaniel

Copy link
Copy Markdown
Member

Problem

Refs #511. Deadline arithmetic such as Workflow::now()->addHour() mutates the executor clock. A caller can also mutate a previously supplied setTime() value.

Change

Copy Carbon values when storing and reading per-fiber time. Preserve mutable/immutable return behavior, timestamp precision, timezone, and the existing wall-clock fallback outside workflow fibers.

Add clock ownership regressions and a database-backed deadline fixture. It remains waiting initially and after the first 30-minute timer, completes after the second durable timer, and replays from freshly loaded models under an unrelated wall clock.

Validation

  • Before the fix: three isolation tests fail; the database deadline workflow completes immediately instead of waiting.
  • After the fix: 11 focused tests / 47 assertions pass on PHP 8.4.25, Laravel 13.31.0, Carbon 3.13.2, SQLite. PHPUnit reports its existing configuration deprecation.
  • Focused PHPStan and ECS pass; public-boundary and whitespace checks pass.
  • Broader repository CI and consumer follow-through remain in progress. This PR is not yet a published-artifact claim.

Delivery

Review embedded consumers and pinned Server images before declaring #511 delivered. No wire-format change or automatic release of unchanged SDKs.

@rmcdaniel
rmcdaniel marked this pull request as ready for review September 12, 2026 09:15
@rmcdaniel

Copy link
Copy Markdown
Member Author

Expanded local qualification: 79 tests / 319 assertions pass across clock ownership, fiber runner, fiber disposal, deterministic time and database-backed deadline replay. The unchanged-implementation counterexample is three failed ownership tests plus the prematurely completed database workflow; source fix is limited to copying on set/read.

Consumer review against current target branches: Server pins Workflow 2.0.13 and needs a dependency update/new image; Sample App locks 2.0.13 and needs a targeted lock update. Waterline does not require Workflow at runtime (its pin is development-only), so unchanged Waterline needs no release. This is not a portable wire-protocol change: PHP/Python/Rust SDK and CLI artifacts do not need version-alignment releases. Embedded applications must update their Workflow dependency.

This PR now includes 2.0.14 release metadata. After CI and merge, verify Packagist and published embedded upgrade paths, then run the deadline/mutation regression against the published package and update the affected pinned consumers. Private deployment follow-through is recorded privately.

@rmcdaniel
rmcdaniel merged commit 259c32b into main Sep 12, 2026
16 checks passed
@rmcdaniel
rmcdaniel deleted the fix/deterministic-clock-copy branch September 12, 2026 09:18
@rmcdaniel

Copy link
Copy Markdown
Member Author

Workflow 2.0.14 is now published at immutable commit 259c32b. Packagist source/dist references match.

Published verification passed: https://github.com/durable-workflow/workflow/actions/runs/34685988306 . This includes all 16 supported published Laravel/PHP upgrade combinations plus platform/package verification. Main source validation, including all database shards and coverage, also passed: https://github.com/durable-workflow/workflow/actions/runs/34685503210 .

Independent installed-package regression: PHP 8.4.25, Laravel 13.31.0, Carbon 3.13.2, file-backed SQLite. Composer-installed Workflow 2.0.13 produced five failures in the eight clock/deadline tests; changing only that dependency to published 2.0.14 produces 8 tests / 33 assertions passing. Reflection verified the implementation was loaded from vendor/durable-workflow/workflow, not the source checkout. The deadline remains pending initially and at 30 minutes, completes at one hour from durable TimerFired history, and fresh-model replay ignores an unrelated future wall clock. Existing PHPUnit configuration deprecation only.

Server pinned-image and Sample App lock follow-through are being completed next. No source substitution in this published-package proof.

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.

2 participants