Documentation
¶
Overview ¶
Package execrecovery implements the execution-recovery contract (R1–R6) used by fixture conformance tests and by direct-execution wait paths.
Index ¶
- Constants
- func ConclusiveFailedReceipt(status string) bool
- func NewIdempotencyKey() (string, error)
- func NonSuccessReceipt(r Receipt) bool
- func ResolveIdempotencyKey(explicit string) (string, error)
- type ConflictError
- type DirectStatus
- type Fixture
- type IdempotencyBody
- type InProgressTimeoutError
- type Kind
- type Options
- type Outcome
- type Receipt
- type Sample
- type SequenceFixture
- type SequenceStep
- type Vocabulary
Constants ¶
const ( CodeIdempotencyConflict = "idempotency_conflict" CodeIdempotencyInProgress = "idempotency_in_progress" )
Codes from KeeperHub/keeperhub lib/idempotency.ts idempotencyEarlyResponse. Both map to HTTP 409; only `code` distinguishes them.
const FixtureVersion = 1
const IdempotencyHeader = "Idempotency-Key"
Variables ¶
This section is empty.
Functions ¶
func ConclusiveFailedReceipt ¶
ConclusiveFailedReceipt reports a chain-answered failure (lib/web3/verify-receipt.ts CONCLUSIVE_STATUSES minus success).
func NewIdempotencyKey ¶
NewIdempotencyKey returns a random UUID-like key for a single write intent. Callers that retry the same intent across process restarts must persist or derive a stable key instead (see docs.keeperhub.com/api/direct-execution).
func NonSuccessReceipt ¶
NonSuccessReceipt is true when a receipt exists and is not explicitly successful.
func ResolveIdempotencyKey ¶
ResolveIdempotencyKey returns explicit if non-empty, otherwise a new key.
Types ¶
type ConflictError ¶
type ConflictError struct {
Body IdempotencyBody
Key string
}
ConflictError is a 409 idempotency_conflict.
func (ConflictError) Error ¶
func (e ConflictError) Error() string
type DirectStatus ¶
type DirectStatus struct {
ExecutionID string `json:"executionId"`
Status string `json:"status"`
Type string `json:"type"`
TransactionHash *string `json:"transactionHash"`
TransactionLink *string `json:"transactionLink"`
Result any `json:"result"`
Error *string `json:"error"`
CreatedAt string `json:"createdAt"`
CompletedAt *string `json:"completedAt"`
Receipts []Receipt `json:"receipts,omitempty"`
}
DirectStatus is the flat wire shape of GET /api/execute/{id}/status. Canonical type: cmd/execute aliases this as ExecStatusResponse.
type Fixture ¶
type Fixture struct {
Name string `json:"-"`
Version int `json:"version"`
Kind Kind `json:"kind"`
Rule string `json:"rule"`
HTTPStatus int `json:"httpStatus"`
RequireChainEvidence bool `json:"requireChainEvidence"`
Expect Outcome `json:"expect"`
Response json.RawMessage `json:"response"`
ResponseRaw string `json:"responseRaw,omitempty"`
Note string `json:"note,omitempty"`
}
Fixture is one conformance case loaded from testdata/execution_recovery_v1.
func LoadFixtureDir ¶
LoadFixtureDir loads every versioned *.json fixture that is not a sequence.
func (Fixture) DecodeResponse ¶
func (f Fixture) DecodeResponse() (DirectStatus, error)
DecodeResponse unmarshals the flat DirectStatus wire body.
type IdempotencyBody ¶
type IdempotencyBody struct {
Error string `json:"error"`
Code string `json:"code"`
Retryable *bool `json:"retryable"`
OriginalExecutionID *string `json:"originalExecutionId"`
}
IdempotencyBody is the 409 JSON from idempotencyEarlyResponse.
func ParseIdempotencyBody ¶
func ParseIdempotencyBody(body []byte) (IdempotencyBody, bool)
ParseIdempotencyBody decodes a 409 body. ok is true when `code` is one of the two idempotency codes, or when retryable is present as a fallback.
func (IdempotencyBody) IsConflict ¶
func (b IdempotencyBody) IsConflict() bool
IsConflict is true when the key is bound to a different payload. The client must fail closed and must not rotate the key.
func (IdempotencyBody) IsInProgress ¶
func (b IdempotencyBody) IsInProgress() bool
IsInProgress is true when the same key is already processing. The client must retry that key and must not mint a new one.
type InProgressTimeoutError ¶
type InProgressTimeoutError struct {
Key string
}
InProgressTimeoutError is returned when 409 idempotency_in_progress outlives the wait budget. The same key must be reused on the next attempt.
func (InProgressTimeoutError) Error ¶
func (e InProgressTimeoutError) Error() string
type Kind ¶
type Kind string
Kind labels how a fixture relates to production.
observed: a response the current handler can emit. defensive: a client-side invariant against a body KEEP-966 makes unreachable. classifier: exercises a classifier option the shipped CLI does not set.
type Options ¶
type Options struct {
// RequireChainEvidence is a classifier-only option used by fixtures.
// The shipped CLI wait paths do not set it. When true, completed
// without a verified successful receipt is Failure.
RequireChainEvidence bool
}
Options controls classification strictness.
type Outcome ¶
type Outcome string
Outcome is the classified result of one status observation.
const ( OutcomePending Outcome = "pending" OutcomeSuccess Outcome = "success" OutcomeFailure Outcome = "failure" // OutcomeUnconfirmed is broadcast-but-unreadable. It is neither success nor // failure: the transaction may already be on chain. Callers stop waiting and // report it; they must not poll it through and must not resubmit. OutcomeUnconfirmed Outcome = "unconfirmed" OutcomeMalformed Outcome = "malformed" OutcomeRateLimited Outcome = "rate_limited" OutcomeUnrecognized Outcome = "unrecognized" )
func Classify ¶
Classify maps one status observation to an Outcome.
Direct-execution statuses are pending|running|unconfirmed|completed|failed (app/api/execute/_lib/types.ts). Workflow run statuses (success|error|cancelled) belong to a different API and must not be fed here — see Vocabulary().
`unconfirmed` maps to OutcomeUnconfirmed, not OutcomePending: the server keeps reconciling that row, but a client must stop waiting on it rather than poll to a failure the chain never reported.
An unknown future status is OutcomeUnrecognized (never success, never malformed) so a server addition does not look like a corrupt body.
type Receipt ¶
type Receipt struct {
Hash string `json:"hash"`
ChainID *int `json:"chainId,omitempty"`
Network string `json:"network,omitempty"`
Verified bool `json:"verified"`
ReceiptStatus string `json:"receiptStatus"`
BlockNumber *int64 `json:"blockNumber,omitempty"`
GasUsed *string `json:"gasUsed,omitempty"`
VerifiedAt string `json:"verifiedAt"`
}
Receipt is GET /api/execute/{id}/status receipts[] (DirectExecutionReceiptEntry in KeeperHub/keeperhub).
receiptStatus values from lib/web3/verify-receipt.ts: success | reverted | not_found | timeout | safe_inner_failure. verifiedAt is required on the server type. chainId is optional.
func FirstBlockingReceipt ¶
FirstBlockingReceipt returns the first receipt that must not be treated as success.
type SequenceFixture ¶
type SequenceFixture struct {
Name string `json:"name"`
Version int `json:"version"`
Kind Kind `json:"kind"`
Rule string `json:"rule"`
Steps []SequenceStep `json:"steps"`
}
SequenceFixture exercises multi-poll recovery (R6).
func LoadSequence ¶
func LoadSequence(path string) (SequenceFixture, error)
LoadSequence loads a multi-step sequence fixture.
func LoadSequenceDir ¶
func LoadSequenceDir(dir string) ([]SequenceFixture, error)
LoadSequenceDir loads every *.sequence.json fixture in dir.
type SequenceStep ¶
type SequenceStep struct {
HTTPStatus int `json:"httpStatus"`
RequireChainEvidence bool `json:"requireChainEvidence"`
Expect Outcome `json:"expect"`
Response json.RawMessage `json:"response"`
ResponseRaw string `json:"responseRaw,omitempty"`
}
SequenceStep is one observation in a multi-response cold-start sequence.
func (SequenceStep) Sample ¶
func (s SequenceStep) Sample() Sample
Sample converts a sequence step into a Classify input.
type Vocabulary ¶
Vocabulary documents which status strings belong to which API surface. Direct-execution and workflow-run statuses must not be mixed.
Pending and Terminal are client wait semantics: Pending means keep polling, Terminal means stop waiting and report. Terminal is not a claim that the server will never change the row again.
func DirectExecutionVocabulary ¶
func DirectExecutionVocabulary() Vocabulary
DirectExecutionVocabulary is GET /api/execute/{id}/status (app/api/execute/_lib/types.ts ExecutionStatus).
`unconfirmed` is listed Terminal in the client sense only. The server documents it as non-terminal and a reconciliation sweep settles it to completed or failed; clients still stop there so that an unreadable receipt never becomes a re-run that broadcasts twice.
func WorkflowRunVocabulary ¶
func WorkflowRunVocabulary() Vocabulary
WorkflowRunVocabulary is GET /api/workflows/executions/{id}/status.