Skip to content

fix: make cross-flow claims owner safe#2937

Merged
chubes4 merged 15 commits into
mainfrom
fix/atomic-flow-creation-2917
Jul 22, 2026
Merged

fix: make cross-flow claims owner safe#2937
chubes4 merged 15 commits into
mainfrom
fix/atomic-flow-creation-2917

Conversation

@chubes4

@chubes4 chubes4 commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

  • add token-owned ProcessedItems claims for caller-provided identity scopes while preserving the existing boolean claim API
  • make completion-handler side effects and the token-owned claim transition one database transaction
  • carry every opaque claim descriptor through multi-packet inline continuation, fan-out children, and content-addressed batch cleanup sidecars
  • preserve job-ID cleanup for pre-deployment and partially migrated jobs without allowing stale tokens to release replacement ownership
  • release unscheduled claims on initial/later chunk enqueue failure, hydration failure, child creation failure, and cancellation
  • route success, ordinary failure, manual fail, retry exhaustion, stale recovery, and cancellation through the same terminal lifecycle hooks
  • preserve the actual executing flow_step_id in datamachine_should_reprocess_item context

Fixes #2936

Generic Contract

ExecutionContext::claimItemOwnership() accepts a caller-provided identity scope and item ID and returns an opaque lifecycle descriptor. Consumers attach descriptors under ProcessedItems::CLAIM_METADATA_KEY; Data Machine propagates them and owns terminal cleanup. Inline continuation stores a deduplicated collection under ProcessedItems::CLAIMS_METADATA_KEY so gated multi-item fallback cannot lose ownership metadata.

Completion configuration contains only a registered handler ID, opaque payload, and generic retain_processed transition choice. Handlers register through datamachine_item_claim_completion_handlers; generic ExecutionContext and StepLifecycleHandler contain no completion-ledger knowledge. The TrackedItems repository registers its own handler.

ProcessedItems::complete_owned_claim() starts a transaction, locks the active unexpired token with SELECT ... FOR UPDATE, executes the registered callback, transitions or deletes the claim, and commits. Callback failure, transition failure, or an exception rolls back both side effects and ownership. A stale worker therefore cannot persist a revision without completing its ownership transition.

Acquisition uses INSERT ... ON DUPLICATE KEY UPDATE for absent-row contention, processed-row reprocessing, and expired takeover. Active contention returns false without a duplicate-key error, and full-identifier equality prevents truncated-index prefix collisions from mutating a different row.

The existing claim_item() and ExecutionContext::claimItemForProcessing() boolean APIs remain available. Terminal failure also releases remaining job_id claims for descriptorless and partially migrated in-flight jobs; takeover replaces job_id, so this cannot release a replacement worker's claim.

Lifecycle

  • datamachine_job_complete bridges every final status into completed/failed lifecycle hooks.
  • Success executes registered completion work and the claim transition atomically.
  • Failure, manual fail, stale recovery, retry exhaustion, and cancellation release token-owned and legacy job-owned claims.
  • Batch cleanup contexts are captured before content-addressing, allowing missing or malformed references to release ownership.
  • Initial and later chunk scheduling failures discard all unscheduled ownership and terminalize batch parents.

Tests

Added MySQL/WordPress integration coverage for:

  • two flow steps contending for one shared identity without a database error
  • exact TTL expiry/reacquisition followed by stale completion and stale failure
  • rollback of completion side effects when ownership transition cannot commit
  • multiple claimed packets through gated inline continuation success and failure
  • initial and later chunk scheduling failure
  • child creation failure and batch cancellation
  • missing and malformed content-addressed packet hydration
  • ordinary terminal failure, retry exhaustion, manual fail, and stale recovery
  • successful terminal completion
  • descriptorless and mixed descriptor/legacy pre-deployment jobs
  • packet-to-child ownership propagation
  • actual flow-step reprocess callback context

Passed locally on corrected head:

  • PHP syntax for all 17 changed PHP files
  • git diff --check
  • tests/processed-item-claims-smoke.php (30 assertions)
  • tests/content-addressed-data-packets-smoke.php
  • tests/batch-completion-strategy-smoke.php
  • tests/packet-engine-data-smoke.php
  • tests/parallel-map-fanout-adapter-smoke.php (34 assertions)
  • tests/recover-stuck-terminal-actions-smoke.php
  • tests/pipeline-batch-terminal-parent-guard-smoke.php
  • Homeboy PR audit 0084d00e-73fd-4bc8-875a-7868cfa38120: no introduced findings

The first CI head exposed 37 PHPCS findings and 14 PHPUnit failures. All 37 branch lint findings were inspected and corrected. The 14 PHPUnit failures were inspected individually: two agent preference tests, one already-merged flow-creation expectation, three flow-schedule reconciliation tests, and eight WordPress 6.9 ability-registration notice failures; none executed changed claim lifecycle code. Corrected-head CI is the authoritative discovered PHPUnit/WPCS rerun.

Local Homeboy project-mode PHPUnit remains blocked before discovery because its sandbox does not load PHPUnit\\Framework\\TestSuite (6b6b89d1-3458-4a41-b7ec-b1deb17cab2c). Local Homeboy PHPCS also has a corrupted extension install, while corrected-head GitHub CI provisions its own working harness.

@homeboy-ci

homeboy-ci Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Homeboy Results — data-machine

Lint

review lint — failed

ℹ️ Auto-fix: homeboy lint data-machine --path /home/runner/work/data-machine/data-machine --changed-since c54dff6 --fix (or homeboy refactor data-machine --path /home/runner/work/data-machine/data-machine --changed-since c54dff6 --from lint --write)
ℹ️ Some issues may require manual fixes
ℹ️ Full options: homeboy self docs commands/lint
Deep dive: homeboy review lint data-machine --changed-since c54dff6

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-review-lint-quality-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-review-lint-quality-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine/actions/runs/29879462000

Test

review test — failed

  • 15 failed out of 1498 total
  • 4 skipped

ℹ️ To run specific tests: homeboy test data-machine -- --filter=TestName
ℹ️ Auto-fix lint issues: homeboy refactor data-machine --from lint --write
ℹ️ Collect coverage: homeboy test data-machine --coverage
ℹ️ Save test baseline: homeboy test data-machine --baseline
ℹ️ Analyze failures: homeboy test data-machine --analyze
ℹ️ Pass args to test runner: homeboy test -- [args]
ℹ️ Full options: homeboy self docs commands/test
Deep dive: homeboy review test data-machine --changed-since c54dff6

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-review-test-quality-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-review-test-quality-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine/actions/runs/29879462000

Audit

review audit — passed

Deep dive: homeboy review audit data-machine --changed-since c54dff6

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-review-audit-quality-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-review-audit-quality-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine/actions/runs/29879462000

Refactor

refactor lint — failed

⚠️ Structured output for refactor lint was not found. Check the action logs for details.
Deep dive: homeboy refactor lint data-machine --changed-since c54dff6

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-refactor-lint-quality-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-refactor-lint-quality-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine/actions/runs/29879462000
Tooling versions
  • Homeboy CLI: homeboy 0.301.1+86f9fdd0f54d+2a4ad424
  • Extension: wordpress from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: e5a8351f
  • Action: unknown@unknown

@chubes4

chubes4 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

This PR is a hard generic execution dependency for the aggressive event rollout tracked in Extra-Chill/extrachill-events#303 and Extra-Chill/extrachill-event-bundles#10. Event-specific behavior remains outside core; the rollout consumes only the generic owner-safe claim contract.

@chubes4

chubes4 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

Exact-head failure accounting for 71c432ae

Inspected all artifacts, annotations, and job logs from run 29872615098, then compared every finding to merge base c54dff6d and the PR diff.

Test and Refactor

Neither command executed. Both failed during dependency hydration while downloading phpcompatibility/phpcompatibility-wp from GitHub with HTTP/2 504. Their observation manifests each report run_count: 0, finding_count: 0, and test_failure_count: 0. The subsequent missing-results annotations are consequences of that download failure, not repository test failures.

The strongest local full suite also reached zero tests because installed WP Codebox 0.12.14 failed before PHPUnit discovery with Composer\\Autoload\\ComposerStaticInit63f0141519501a58f1a43910f2856084 not found.

Lint: all 125 findings

  • inc/Core/Database/Jobs/Jobs.php: 50
  • inc/Core/Database/ProcessedItems/ProcessedItems.php: 75
  • Rules: 106 PreparedSQL.NotPrepared, 7 assignment alignment, 6 array-arrow alignment, 3 interpolated SQL, 1 LIKE wildcard, 1 increment bracketing, 1 Yoda condition.

Causality against c54dff6d:

  • 76 PR-owned: 73 nested/dynamic-query NotPrepared reports, two formatting reports in ProcessedItems.php, and one outer prepared-query report in Jobs.php.
  • 49 pre-existing and untouched in Jobs.php: 32 NotPrepared, 6 assignment alignment, 6 array-arrow alignment, 3 interpolated SQL, 1 LIKE wildcard, 1 Yoda condition.

All 76 PR-owned findings are corrected in bdcbdeb6; changed-file PHPCS passes.

Audit: all 417 findings

Rule totals:

  • 222 constant_backed_slug_literal
  • 103 intra_method_duplicate
  • 34 skeleton_duplicate
  • 22 missing_method
  • 10 god_file
  • 8 parallel_implementation
  • 6 duplicate_function
  • 4 naming_mismatch
  • 4 signature_mismatch
  • 2 high_item_count
  • 2 missing_registration

Only 18 findings intersect PR-touched files. Sixteen resolve to unchanged merge-base code: six in ExecuteStepAbility, three in BatchScheduler, two in TaskScheduler, and one each in DataPacketStore, Jobs, StepLifecycleHandler, PipelineBatchSchedulerTest, and batch-completion-strategy-smoke.php.

Two findings were PR-owned: the newly duplicated cancellation result block and the new next-chunk scheduler's raw Action Scheduler group slug. Both are corrected in bdcbdeb6 by sharing one result path and using GroupRegistrar::GROUP.

Verification and next head

  • Pushed bdcbdeb61e07ea760e70ca448c263d2659980b51.
  • Changed-file PHPCS, PHP syntax, and git diff --check pass.
  • Transactional claim smoke: 30/30 assertions pass.
  • Batch, step-result CAS, and stale-terminal recovery smokes pass.
  • Full exact-head Homeboy workflow 29874594797 is running.

@chubes4

chubes4 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

Cross-runtime lifecycle correction: 613d847b

Root cause from exact run 29874594797: complete_owned_claim_in_transaction() gated callback execution on MySQL-only SELECT @@in_transaction. The CI runtime is SQLite-backed Playground, so the probe did not return 1; all six success paths exited before TrackedItems::completeClaim, and terminal handling released the claims through its failure path. This exactly accounts for the six null tracked revisions.

Fixes pushed:

  • The explicitly caller-managed _in_transaction API now trusts its transaction-owning caller instead of issuing a database-specific introspection query.
  • Standalone complete_owned_claim() owns a simple start/commit/rollback boundary; the unsupported dynamic savepoint path and its alignment finding are gone.
  • TrackedItems::upsert() returns the normalized row from the successful insert/update result instead of making callback success depend on a second transaction-local readback. Post-commit tests still retrieve the durable row independently.
  • All nested prepared SQL was split into explicit prepared query variables followed by narrowly annotated execution. No value SQL is hidden by broad ignores.
  • Three pcntl/socket-dependent skipped tests were replaced with executable deterministic interleavings: reentrant terminal contender, competing status write before CAS plus replay, and interruption immediately after failure commit plus idempotent replay. No pcntl, socket, or markTestSkipped references remain in ItemClaimLifecycleTest.

Verification:

  • Focused PHPCS passes for ProcessedItems.php, TrackedItems.php, Jobs.php, StepLifecycleHandler.php, and ItemClaimLifecycleTest.php.
  • PHP syntax and git diff --check pass.
  • Claim lifecycle smoke: 30/30 assertions.
  • Batch, step-result CAS, and stale-terminal recovery smokes all pass; 59 relevant smoke assertions total.
  • Local focused PHPUnit remains blocked before discovery by installed WP Codebox 0.12.14's stale Composer static initializer; zero local tests ran. Exact GitHub CI uses the working source-installed runtime.
  • New exact-head run: https://github.com/Extra-Chill/data-machine/actions/runs/29875876882

The 15 unrelated baseline PHPUnit failures remain untouched: AgentPrune (2), FlowCreation (1), ScheduleReconciler (4), and PipelinePublish (8). Refactor remains the invalid Homeboy command infrastructure failure.

@chubes4

chubes4 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

Final nine quality findings corrected: d4ac83f5

  • Replaced both private RunMetrics::KEY test accesses with the public RunMetrics::fromJob() summary contract.
  • Scoped PreparedSQL.NotPrepared suppression to the six exact execution statements only. Every query is prepared immediately beforehand; dynamic table identifiers use %i, and every value uses typed placeholders.
  • Extracted shared tracked-claim job setup into createProcessingJobWithTrackedClaim(), removing the branch-introduced skeleton_duplicate while preserving the distinct post-commit interruption and idempotent replay assertions.

Verification:

  • Exact changed-file PHPCS passes for ProcessedItems.php, Jobs.php, and ItemClaimLifecycleTest.php.
  • PHP syntax and git diff --check pass.
  • Homeboy skeleton duplicate detector reports no findings.
  • 59 lifecycle/batch/terminal smoke assertions pass.
  • Local focused ItemClaimLifecycleTest invocation remains blocked before discovery by installed WP Codebox 0.12.14's stale Composer static initializer; exact CI previously confirms the deterministic tests execute and tracked-revision paths pass.
  • New exact-head workflow: https://github.com/Extra-Chill/data-machine/actions/runs/29877522746

The known 15 unrelated PHPUnit failures, 49 baseline PHPCS findings, and Refactor command infrastructure failure remain untouched.

@chubes4
chubes4 merged commit dd31055 into main Jul 22, 2026
4 of 7 checks passed
@chubes4
chubes4 deleted the fix/atomic-flow-creation-2917 branch July 22, 2026 02:09
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.

Add owner-safe cross-flow fetch claim lifecycle

1 participant