package api // Per-request dispatch state machine for the consumer inference path. // // This file holds the speculative TTFT-aware dispatch loop that handleChatCompletions // drives: it picks a provider (or queues), waits for the first CONTENT chunk with a // speculative backup race, fails over invisibly on provider error/timeout up to // maxDispatchAttempts, and commits exactly once. It is a PURELY STRUCTURAL extraction // of what previously lived inline in consumer.go — every select arm, timer Stop/Reset, // channel-close+ErrorCh grace window, heldChunks cap, liveness extension, speculative // race (backup dispatch / cancel-loser / skipBackup), refund-exactly-once, breaker // call, DD metric, and status code is preserved exactly. // // Control-flow mapping (former labeled blocks → methods): // // for attempt := range maxDispatchAttempts → dispatchState.run (the orchestrator) // dispatch-primary block (incl. queue path) → dispatchState.dispatchPrimary // firstChunkWait + speculative race → dispatchState.waitFirstChunk // noBackupWait → dispatchState.waitNoBackup // race + sub-waits → dispatchState.runRace // backupFailedPrimaryWait → dispatchState.raceBackupFailedWaitPrimary // primaryFailedBackupWait → dispatchState.racePrimaryFailedWaitBackup // backupFailedWaitPrimary → dispatchState.raceBackupErrWaitPrimary // acceptedWait → dispatchState.waitAccepted // // The former labeled jumps become method returns: `continue dispatch` → outcomeRetry, // `break`/commit → outcomeCommitted, `break