aarondb/continuation

continuation — deterministic transient-failure policy

This is a pure model for resuming approved work after a provider or transport interruption. An adapter persists Checkpoint and performs the chosen effect; this module never retries, sleeps, switches providers, or files an issue itself.

Types

Checkpoint is the complete durable value an adapter must save after every decision. Reloading it with resume is identity-preserving and cannot repeat an already recorded effect.

pub type Checkpoint {
  Checkpoint(continuation: Continuation)
}

Constructors

pub type Continuation {
  Continuation(
    work: Work,
    policy: RetryPolicy,
    provider_index: Int,
    retry_count: Int,
    evidence: option.Option(Evidence),
    completed_effect_keys: List(String),
    status: Status,
  )
}

Constructors

pub type EffectPermit {
  EffectAuthorized
  EffectAlreadyCompleted
}

Constructors

  • EffectAuthorized
  • EffectAlreadyCompleted
pub type Evidence {
  Evidence(
    request_id: String,
    failure_class: FailureClass,
    first_failed_at_ms: Int,
    last_failed_at_ms: Int,
    message: String,
  )
}

Constructors

  • Evidence(
      request_id: String,
      failure_class: FailureClass,
      first_failed_at_ms: Int,
      last_failed_at_ms: Int,
      message: String,
    )
pub type FailureClass {
  Transient
  ProviderOverloaded
  Permanent
}

Constructors

  • Transient
  • ProviderOverloaded
  • Permanent
pub type FallbackOutcome {
  NoFallbackAvailable
  FallbackSelected(provider: String)
  FallbackExhausted
}

Constructors

  • NoFallbackAvailable
  • FallbackSelected(provider: String)
  • FallbackExhausted
pub type IssuePayload {
  IssuePayload(
    plan_id: String,
    task_id: String,
    effect_key: String,
    request_id: String,
    first_failed_at_ms: Int,
    last_failed_at_ms: Int,
    failure_class: FailureClass,
    retry_count: Int,
    fallback_outcome: FallbackOutcome,
    message: String,
  )
}

Constructors

  • IssuePayload(
      plan_id: String,
      task_id: String,
      effect_key: String,
      request_id: String,
      first_failed_at_ms: Int,
      last_failed_at_ms: Int,
      failure_class: FailureClass,
      retry_count: Int,
      fallback_outcome: FallbackOutcome,
      message: String,
    )
pub type RetryPolicy {
  RetryPolicy(
    max_retries_per_provider: Int,
    base_backoff_ms: Int,
    providers: List(String),
  )
}

Constructors

  • RetryPolicy(
      max_retries_per_provider: Int,
      base_backoff_ms: Int,
      providers: List(String),
    )
pub type Status {
  Ready
  Waiting(retry_at_ms: Int)
  SwitchedToFallback(provider: String)
  Escalated(payload: IssuePayload)
  Completed
}

Constructors

  • Ready
  • Waiting(retry_at_ms: Int)
  • SwitchedToFallback(provider: String)
  • Escalated(payload: IssuePayload)
  • Completed
pub type Work {
  Work(plan_id: String, task_id: String, effect_key: String)
}

Constructors

  • Work(plan_id: String, task_id: String, effect_key: String)

Values

pub fn checkpoint(continuation: Continuation) -> Checkpoint
pub fn current_provider(
  continuation: Continuation,
) -> option.Option(String)
pub fn fail(
  continuation: Continuation,
  request_id: String,
  failure_class: FailureClass,
  message: String,
  now_ms: Int,
) -> Continuation

Decide the next retry/fallback/escalation transition for a failure observed at now_ms. A permanent failure never retries. Backoff is deterministic linear data: base_backoff_ms * next_retry_count.

pub fn new(work: Work, policy: RetryPolicy) -> Continuation
pub fn permit_effect(continuation: Continuation) -> EffectPermit

The adapter asks permission before performing the named external effect.

pub fn record_effect(continuation: Continuation) -> Continuation

Record completion before acknowledging an effect. Repeating this operation is deliberately idempotent so an interrupted acknowledgement cannot duplicate it.

pub fn resume(checkpoint: Checkpoint) -> Continuation
Search Document