Skip to content

fix(scheduling): prove every #[Scheduled] duration at boot and read ISO-8601 durations (26.09.11) - #10

Merged
ancongui merged 2 commits into
mainfrom
fix/scheduling-iso-durations
Oct 1, 2026
Merged

ancongui merged 2 commits into
mainfrom
fix/scheduling-iso-durations

Conversation

@ancongui

@ancongui ancongui commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Every #[Scheduled] duration is proved at boot. fixedRate, fixedDelay and lockTtl are now parsed by ScheduleWiringPass::run(), as initialDelay already was, and an unparseable value refuses the boot naming its method. lockTtl used to be parsed only inside the task closure: an invalid value threw on every tick, was reported, and the task never ran while the application booted and looked healthy.
  • ISO-8601 durations. Firefly\Resilience\Duration::parse also reads PT14M, PT1H30M, P1D, PT0.25S — the java.time.Duration form Spring's @Scheduled reads. Years, months and weeks are refused because their length is not fixed. Resilience settings and every scheduling duration accept it.
  • Release preparation for 26.09.11 (version constant, badge, publishing/versioning pages, CHANGELOG).

Found while deploying Signature CRM to Azure Container Apps: its seven scheduled tasks declared lockTtl: 'PT14M' and none of them ever ran in production mode; the only trace was a generic ConfigurationException in the logs.

Verification

  • New tests: DurationTest (ISO-8601 accepted and refused cases), ScheduleWiringPassTest (boot refusal for lockTtl, fixedRate, fixedDelay; ISO lockTtl reaches the lock as 240 s).
  • composer validate --strict, composer mono-validate, composer check (Pint, PHPStan, 4,189 tests passed, 6 skipped, deptrac 0 violations) and composer test:package all passed locally.
  • The CRM's scheduled tasks run through the fixed wiring without a reported error (new ScheduledTasksTest in the CRM).

Andres Contreras added 2 commits September 30, 2026 21:02
…SO-8601 durations are read as Spring reads them

lockTtl was parsed only inside the task closure, so a value Duration::parse
refused threw on every tick, was reported and the task never ran while the
application booted and looked healthy. ScheduleWiringPass now parses
fixedRate, fixedDelay and lockTtl at boot, as it already parsed
initialDelay, and refuses the boot naming the method.

Duration::parse also accepts ISO-8601 durations (PT14M, PT1H30M, P1D,
PT0.25S), the java.time.Duration form Spring's @scheduled reads. Years,
months and weeks are refused because their length is not fixed.

Found in a Signature CRM deployment whose seven scheduled tasks declared
lockTtl: 'PT14M' and never ran.
@ancongui
ancongui merged commit 8bbad67 into main Oct 1, 2026
7 checks passed
@ancongui
ancongui deleted the fix/scheduling-iso-durations branch October 1, 2026 04:50
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