feat(parallel): let any number of same-class tasks be in flight at once - #25
Merged
Merged
Conversation
Two RenderJobs was the most natural thing a user could try, and it was refused: the substrate's registry keyed a persisted graph by class name, so a second persist of one class was an upsert that would have released the graph a running worker was still reading. The refusal was the only safe behaviour available on this side of the line - and now the line has moved. The substrate keys graphs per instance (lisachenko/php-shared-data-extension#23), so the runtime simply stops refusing: - SharedArena::persist() rides persistInstance(): each task graph's registry entry is named by its own root address, a second instance is a second entry, and nothing supersedes anything. - Shared roots are filed under the name they were declared with, not the class - so two declareShared() roots of one class, which the class keying quietly broke too, are now two graphs. - ArenaTaskDirectory drops the in-flight ledger, the refusal and releaseInFlight(); WorkerSupervisor drops the dispatched map that existed only to feed it. What route 2 costs instead is stated in the directory's docblock: arena memory per unpublished spawn, held until family teardown - publish tasks for steady-state workloads. Each panic is now its own SharedError instance graph as well, so two workers failing near-simultaneously each leave an error their waiter can still attach - previously the second capture superseded the first worker's registry entry. Tests pin all three acceptance criteria of #15: two same-class tasks in flight at once with each awaiting its own result; both graphs read back intact through shared memory while both run (asserted, not assumed); the pre-fork publishTask() route untouched by the whole existing suite. Plus a test for two same-class roots and one for two concurrent panics keeping their own errors. The arena-watermark soak's RSS verdict fails identically on unmodified main and is tracked separately in #24. Requires lisachenko/php-shared-data-extension#23; CI on this branch is red until that merges into the substrate's main. Closes #15 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5QRWPfmkZME7hDjU6i5EA
Owner
Author
|
CI status, verified from the job logs: all four failures (Tests + PHPStan, both minors) are the declared dependency and nothing else — the runners resolved Unblock path: merge lisachenko/php-shared-data-extension#23 (green, 8/8 jobs), then CI here re-runs against the new Generated by Claude Code |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5QRWPfmkZME7hDjU6i5EA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #15 — Option 1, per-instance keys upstream. Depends on lisachenko/php-shared-data-extension#23; CI here stays red until that merges into the substrate's
main(this repo requires it asdev-main).What this does
The substrate now registers a persisted graph under a name minted from its own root address (
persistInstance()), so a second instance of one class is a second entry — never an upsert, never a release under a running worker's feet. With the hazard gone at the source, the runtime deletes its guard rather than keeping a softened version:SharedArena::persist()ridespersistInstance(). Each task graph has its own registry entry; any number of one class are live at once.declareShared()roots of one class used to upsert each other's entries. New test pins twoSharedCounterroots mutated independently.ArenaTaskDirectorydrops the in-flight ledger, the refusal, andreleaseInFlight();WorkerSupervisordrops thedispatchedmap that existed only to feed it. The honest cost statement replaces the limit in the docblock and in AGENTS/README: an unpublished spawn clones its graph into the arena and that memory lives until family teardown — steady-state workloads publish before the fork, which allocates nothing per spawn.SharedError. Previously a second worker's capture superseded the first worker's registry entry, so a waiter attaching the first error's address after that found nothing. New test drives two concurrently panicking workers and asserts each waiter reads exactly its own message.Acceptance criteria from #15
await()s its own result —testTwoTasksOfOneClassAreInFlightAtOnce.phptpins two napping same-class tasks to two workers so their lifetimes genuinely overlap.publishTask()route keeps working unchanged — the entire existing suite drives it; no published-route code changed.Verification
OK (97 tests, 97 assertions)on PHP 8.4 against a vendor tree carrying the substrate branch (94 existing + 3 new).main(24 KiB at 40 rounds, scaling with rounds, arena metrics byte-flat) — a pre-existing parent-side native-memory accumulation, filed as soak-arena-watermark reports a steady parent-side RSS climb the arena metrics do not see #24 rather than folded in here.🤖 Generated with Claude Code
https://claude.ai/code/session_01U5QRWPfmkZME7hDjU6i5EA
Generated by Claude Code