Skip to content

sdk-go: durable steps in the executor client #929

Description

@kartikeya-27

PR #928 shipped the executor client with side_channel and lease. It does not
advertise steps, and this is the other half.

steps is the one capability that fails rather than degrades: a durable step
that silently did not commit is a step that will re-run a charge. So the client
does not advertise it today, which is the contract's own rule rather than a gap
left open by accident — a step call simply is not available.

What it needs, none of which the wire hands over:

  • A local StepSequence. crates/flexiq-core/src/step/sequence.rs is the
    reference and is core-internal; a Go executor reimplements it. seq is
    gapless, 0-based, and equals the number of rows already stored — not the
    positional cursor, because a keyed hit can land out of order and leave the
    cursor behind.
  • Snapshot decoding. JobStepsFrame.snapshot is a JSON metadata array, one
    \n, then every step's blob concatenated in seq order, each blob's length
    taken from that step's result_len. The decoder must be strict: a snapshot
    that silently came back short is a memo that silently went missing. No frame
    means an empty snapshot, never an unknown one.
  • step_key derivation. name#occurrence unkeyed, name:key keyed. The
    occurrence counter is per name and per attempt, and a refused request does not
    spend one. A keyed call never touches the counter, so adding one cannot shift a
    later unkeyed call's number.
  • Ack correlation on (job_id, seq). Register the waiter before sending
    the commit — a fast scheduler can answer before anyone is listening. The wait
    is bounded by min(step_ack_timeout, the job's remaining timeout). already
    is a success: it is a retransmission after a lost ack.
  • The two-phase sleep. step_commit with kind: Sleep and a candidate
    deadline, then — only after the ack, which echoes the deadline storage actually
    settled on — a slept frame that ends the attempt. A deadline already elapsed
    is an ordinary memo hit and sends no frame at all.
  • Refusal classification from the enum, never the message. StepFailure is
    retryable, permanent or superseded, and a superseded commit means another
    attempt owns this job now and this one must stop without writing.

Every step frame carries the dispatch's lease, like every other frame that
advances an attempt.

Prerequisite reading: crates/flexiq-core/BINDING_CONTRACT.md, the durable-step
sections; contracts/REMOTE_SDK_CONTRACT.md.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Opportunisticarea/sdk-goGo remote SDKenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions