Repository navigation
Start namespace-unique instances for scheduled workflows - #977
Conversation
…#874) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Workflow instance IDs are global but schedule IDs are unique per namespace, so the same schedule ID in two namespaces collided on the same occurrence. Schedules outside the configured default namespace now use a reserved schedule@ form with a namespace hash and a length-prefixed schedule ID, bounded to the 191-byte instance key; default-namespace IDs are unchanged. Refs #874 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use a valid schedule.ns:{namespace hash}:{length}:{schedule_id}:{suffix}
form for all new scheduled starts, independent of the configured default
namespace, and hash schedule IDs that exceed the bound or the instance ID
alphabet. Tests use the established UTC test clock and add validator,
default-namespace change and pre-upgrade schedule-history dedupe controls.
Refs #874
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Security bounded source/metadata review of exact head The new default-starter identity is structurally separate from the legacy The correction uses the schedule row namespace rather than mutable current configuration. The default-change, same-millisecond manual/tick, two-namespace backfill, delimiter, bounded fallback and repeat-backfill controls cover the important collision paths. Legacy IDs remain loadable because no reader changes; an already-fired legacy occurrence remains deduplicated by its real schedule-history event, while the next occurrence moves to the new form. The replay-corpus assertion exercises the same default starter rather than only inspecting a helper. The final delta from executed source General has recorded the focused PostgreSQL/Redis counterfactual and positive run. Current exact-head hosted checks are green except the still-running ordinary unit-contract aggregate; the one full build, protected merge/release, and installed published-artifact acceptance remain independent gates. This review creates no PHP Server release. |
|
General's corrected-source qualification passes at
The first Normal PR checks and the single full build are the remaining source qualification gates. General retains protected merge, the routine Core patch publication and installed-package acceptance. No PHP Server release or native source change is included. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #977 +/- ##
=======================================
Coverage 93.99% 94.00%
=======================================
Files 592 592
Lines 81998 82000 +2
=======================================
+ Hits 77077 77082 +5
+ Misses 4921 4918 -3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Status at exact head
Next action: if attempt 2 passes, General takes review, merge, Core 2.15.15 publication and installed acceptance. If it fails again on these tests, treat it as a harness defect to investigate. Don't merge unchanged. |
|
Full build Source handoff: no further edits are planned at |



Fixes #874.
Problem
Workflow instance IDs are a global primary key, but schedule IDs are unique only within a namespace. The default schedule starter named instances
schedule:{schedule_id}:{suffix}without the namespace. As a result, the same schedule ID in two namespaces competed for one instance ID for the same occurrence. The second namespace's backfill, tick or manual trigger then failed withWorkflow instance [...] cannot be reused with a different namespace.Change
PhpClassScheduleStarter::instanceId(): every new scheduled start, whatever the configured default namespace, now usesschedule.ns:{sha256(namespace)[0..32]}:{byte length of schedule_id}:{schedule_id}:{suffix}WorkflowInstanceIdallows (A-Z a-z 0-9 . _ : -).schedule:{schedule_id}:{suffix}ID; the two forms differ at the 9th character.:.h:{sha256(schedule_id)}.hcan't be read as a length.hasFiredOccurrence).The metadata prepares Core 2.15.15 (Composer
product-trainand the changelog heading). The tag isn't created.Tests
tests/Feature/V2/V2ScheduleNamespaceInstanceIdTest.php:tenant-atotenant-b, doesn't produce a shared ID.ScheduleTriggeredhistory recorded, stays readable. Its occurrence stays deduplicated, and the next occurrence starts under the new form without colliding.Replay corpus:
schedule-namespace-instance-identity, plus an assertion keyed to that fixture inV2EmbeddedReplayRegressionCorpusTest. The starter sits under thesrc/V2/Support/*.phpreplay guard, and this backfill fails onmain.Evidence
Focused before/after (General's containers: PHP 8.3.36, PostgreSQL 17.11, Redis 7.4), covering
V2ScheduleNamespaceInstanceIdTest,V2ScheduleTest,V2ScheduleTimezoneTestandV2EmbeddedReplayRegressionCorpusTest:main(b73a55e4) with the current testsdf1bcc69)The backfill, default-change and corpus controls reproduce the original collision on main. Focused PHPStan is clean on the 3 changed PHP files.
e240005fis an ECS-only formatting delta, and230b6a93adds the 2.15.15 metadata.First candidate (
cacc81bf), corrected before this head: 124 tests, 4 errors and 1 failure. Theschedule@form failedWorkflowInstanceIdvalidation. The new tests used a CarbonZtimezone that the test clock rejects. And keeping the legacy form for the configured default namespace still collided after that default changed.Normal PR checks and one full
buildon this exact head will follow.🤖 Generated with Claude Code