Skip to content

Rename RestartExecution/s to ClaimFunction/s and add owner-guarded SetFunction#190

Open
stidsborg wants to merge 1 commit into
mainfrom
claim-function-refactor
Open

Rename RestartExecution/s to ClaimFunction/s and add owner-guarded SetFunction#190
stidsborg wants to merge 1 commit into
mainfrom
claim-function-refactor

Conversation

@stidsborg

@stidsborg stidsborg commented Jul 11, 2026

Copy link
Copy Markdown
Owner

What & why

Groundwork that renames the store-level "restart" primitives to what they actually do — claim (take over ownership of a flow and return its current state) — and adds an owner-guarded state-setter. This unblocks a follow-up simplification of TryInlinePendingMessages (inlining a completed flow's late messages), which becomes: ClaimFunction → merge messages into the effect snapshot → SetFunction(status, owner: null, effects: merged, result: claimed.Result, expectedReplica: self, storageSession: claimed.StorageSession) → clear rows — a single owner-guarded write with no merge-write-verify retry loop.

Changes

  • Rename IFunctionStore.RestartExecution → ClaimFunction, RestartExecutions → ClaimFunctions across the interface, all four stores + their SqlGenerators, test doubles, call sites (incl. PostponedWatchdog) and store test templates.
    • Kept unchanged (names only; store calls repointed): FlowsManager.RestartExecutions(IEnumerable<StoredMessages>) (message-delivery orchestration), InvocationHelper.RestartFunction, and the RestartedFunction record.
  • Add IFunctionStore.SetFunction — an owner-guarded general state-setter:
    Task<bool> SetFunction(StoredId storedId, Status status, byte[]? param, byte[]? result,
        StoredException? exception, long expires, long timestamp,
        ReplicaId? owner,                       // null => release (owner -> NULL)
        IReadOnlyList<StoredEffect>? effects,   // null => leave effects column untouched
        ReplicaId expectedReplica,              // non-nullable: caller must already own the flow
        IStorageSession? storageSession);       // store's forward-carried context (from ClaimFunction)
    Writes status/owner/effects in a single UPDATE guarded by owner = expectedReplica; returns true iff the guard matched. expectedReplica is non-nullable — a caller must own the flow to use it (matching Succeed/Fail). The final storageSession is the store's opaque per-flow context; when supplied it's kept coherent with the persisted effect snapshot, mirroring each store's EffectsStore.SetEffectResults bookkeeping (InMemory advances Version/RowExists/Effects; the SQL stores update Effects/RowExists under owner-based concurrency).
  • Surface result bytes on the claim — add Result to StoredFlowWithEffects (StorageSession kept last), populated from result_json (SQL stores) / in-memory state, so a claimer can feed the flow's current result into SetFunction without nulling it.

Validation

  • dotnet build — 0 errors, 0 warnings.
  • InMemory core suite — 521 passed, 0 failed.
  • ClaimFunction + SetFunction18 passed each on InMemory / Postgres / SqlServer / MariaDB (incl. a session-threading test asserting the session stays coherent after SetFunction).
  • Full PostgreSQL suite — 373 passed, 0 failed.

No behavior change to existing flows — pure rename + additive owner-guarded primitive + additive Result field.

🤖 Generated with Claude Code

@stidsborg stidsborg force-pushed the claim-function-refactor branch from 1417785 to dcb8af0 Compare July 11, 2026 09:19
…tFunction

The store's RestartExecution/RestartExecutions really take over ownership of a flow and hand back its current state, so rename them to ClaimFunction/ClaimFunctions across the IFunctionStore interface, all four stores and their SqlGenerators, the test doubles and the store test templates. The higher-level FlowsManager.RestartExecutions(messages) orchestration, InvocationHelper.RestartFunction and the RestartedFunction record keep their names; only their store calls are repointed.

Add IFunctionStore.SetFunction: an owner-guarded general state-setter that writes status, owner (null releases) and, when provided, the effects snapshot in a single UPDATE guarded by owner = expectedReplica. expectedReplica is non-nullable - the caller must already own the flow - matching the terminal writers. Its final IStorageSession? parameter is the store's forward-carried per-flow context (typically handed back by ClaimFunction); when supplied it is kept coherent with the persisted effect snapshot, mirroring each store's EffectsStore.SetEffectResults bookkeeping. Together with ClaimFunction this gives a claim-commit-release primitive without bespoke SQL.

Surface the flow's current result bytes on the claim result by adding Result to StoredFlowWithEffects (StorageSession kept last), populated from result_json (SQL stores) and the in-memory state, so a caller can pass it straight into SetFunction without nulling the result.

Build clean; InMemory 521 passed; ClaimFunction/SetFunction green on Postgres/SqlServer/MariaDB; full PostgreSQL suite 373 passed.
@stidsborg stidsborg force-pushed the claim-function-refactor branch from dcb8af0 to 4bcea88 Compare July 11, 2026 09:43
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