Defect
On SQLite, ScheduleManager::tick() can miss a schedule during its exact due second. With a once-per-minute trigger this delays dispatch by one full minute and turns the original occurrence into backfill.
WorkflowSchedule persists next_fire_at with six fractional digits (Y-m-d H:i:s.u). The due query passes now() as a DateTime binding; Laravel's connection grammar serializes it to whole seconds. SQLite compares its stored timestamps as text, so 2026-01-01 12:00:00.000000 is greater than 2026-01-01 12:00:00.
Confirmed on current main / Workflow 2.0.11 with PHP 8.4 and Laravel 13: a persisted/reloaded schedule due exactly at frozen 2026-01-01 12:00:00.000000 UTC yields an empty tick instead of a start. The current implementation is also present in 2.0.9. No lost workflow data was observed; this is late dispatch.
Acceptance
- Use the model's persisted timestamp precision for the due predicate without changing global connection date serialization.
- Test exact whole-second equality, exact fractional equality, elapsed time within the same second, and a future fractional deadline that must not start early.
- Verify original occurrence identity, at-most-one dispatch on repeated ticks, and existing namespace fairness/overlap behavior.
- Qualify SQLite plus supported MySQL/PostgreSQL behavior; publish the fix and inspect affected downstream consumers before marking delivery complete.
A focused regression is being added to V2ScheduleTest; no scheduler replacement, polling-frequency workaround or protocol change is needed.
Defect
On SQLite,
ScheduleManager::tick()can miss a schedule during its exact due second. With a once-per-minute trigger this delays dispatch by one full minute and turns the original occurrence into backfill.WorkflowSchedulepersistsnext_fire_atwith six fractional digits (Y-m-d H:i:s.u). The due query passesnow()as a DateTime binding; Laravel's connection grammar serializes it to whole seconds. SQLite compares its stored timestamps as text, so2026-01-01 12:00:00.000000is greater than2026-01-01 12:00:00.Confirmed on current main / Workflow 2.0.11 with PHP 8.4 and Laravel 13: a persisted/reloaded schedule due exactly at frozen
2026-01-01 12:00:00.000000 UTCyields an empty tick instead of a start. The current implementation is also present in 2.0.9. No lost workflow data was observed; this is late dispatch.Acceptance
A focused regression is being added to
V2ScheduleTest; no scheduler replacement, polling-frequency workaround or protocol change is needed.