Changeset 0.22.2 (#96)
This commit is contained in:
59
server/routing/fallback.go
Normal file
59
server/routing/fallback.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
// ── Fallback Runner ─────────────────────────
|
||||
|
||||
// DispatchFunc is called by the fallback runner to attempt a request
|
||||
// against a specific candidate. Returns nil on success, error on failure.
|
||||
// The caller is responsible for setting up SSE headers, streaming, etc.
|
||||
// This is NOT the actual dispatch — it's the "try this candidate" callback.
|
||||
type DispatchFunc func(candidate Candidate) error
|
||||
|
||||
// RunWithFallback tries candidates in order until one succeeds.
|
||||
// Returns the candidate that succeeded, the decision (updated with fallback
|
||||
// depth), and any error if all candidates fail.
|
||||
//
|
||||
// maxRetries controls how many fallback attempts are made beyond the first.
|
||||
// maxRetries=0 means only try the first candidate (no fallback).
|
||||
// maxRetries=-1 means try all candidates.
|
||||
func RunWithFallback(candidates []Candidate, decision *Decision, maxRetries int, dispatch DispatchFunc) (Candidate, *Decision, error) {
|
||||
if len(candidates) == 0 {
|
||||
return Candidate{}, decision, fmt.Errorf("no routing candidates available")
|
||||
}
|
||||
|
||||
// Determine how many candidates to try
|
||||
limit := 1 // just the first
|
||||
if maxRetries < 0 {
|
||||
limit = len(candidates) // try all
|
||||
} else if maxRetries > 0 {
|
||||
limit = 1 + maxRetries
|
||||
if limit > len(candidates) {
|
||||
limit = len(candidates)
|
||||
}
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
for i := 0; i < limit; i++ {
|
||||
c := candidates[i]
|
||||
err := dispatch(c)
|
||||
if err == nil {
|
||||
// Success
|
||||
if decision != nil {
|
||||
decision.Selected = c.ConfigID
|
||||
decision.FallbackDepth = i
|
||||
}
|
||||
return c, decision, nil
|
||||
}
|
||||
|
||||
lastErr = err
|
||||
if i < limit-1 {
|
||||
log.Printf("[routing] candidate %s (%s) failed: %v — trying next", c.ConfigID, c.ProviderID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return Candidate{}, decision, fmt.Errorf("all %d routing candidates failed; last error: %w", limit, lastErr)
|
||||
}
|
||||
Reference in New Issue
Block a user