Skip to content

Per-handler idempotency review + TaskResult.Output engine extension #174

@bdchatham

Description

@bdchatham

Two follow-ups surfaced during the Coral cross-review of PR #175 (gov-vote handler).

1. Per-handler idempotency review template

PR #175 documents in `gov_vote.go` that the engine's crash-rehydration path is safe specifically because MsgVote is chain-idempotent (last-write-wins on `(proposalID, voter)`). Future sign-tx handlers — MsgSend, MsgWithdrawDelegatorReward, MsgDelegate, etc. — do NOT have chain-side idempotency. Copying the gov-vote pattern blindly would double-spend on crash-after-broadcast.

Action when the next non-idempotent sign-tx handler ships:

  • Persist a "broadcast-attempted, txHash=H" marker to SQLite before calling `BroadcastSync`
  • On rehydration, `QueryTx(H)` first — if found, treat handler as completed; only re-broadcast if the chain has no record
  • Add a per-handler doc comment matching the gov-vote template stating which idempotency guarantee applies

When to do this: when the next sign-tx handler (likely gov-submit-proposal #163-C or a staking task) is proposed — not as a speculative refactor. The pre-broadcast marker has its own failure window (between hash compute and the SQLite write) so it deserves real design.

2. `TaskResult.Output` engine extension

`TaskResult` currently exposes only `Status`/`Error`/timestamps. Sign-tx handlers' structured output (`txHash`, `height`, `sequence`, `inclusionStatus`, etc.) is logged but not returned via the engine's task-result surface. Operators must grep the sidecar logs or chain by memo (`taskID=`) for tx outcome.

Acceptable for MVP because:

  • The chain is the genuine source of truth
  • The memo carries the task UUID for forensic correlation
  • Adding `Output any` is a one-way door: storage schema change, `/tasks/{id}` JSON contract change, every other handler suddenly nullable-output

When to do this: when a second sign-tx handler ships and the demand for structured output is concrete (not speculative). At that point design the `Output` shape against two real consumers rather than over-engineering for one.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions