Wire wake and identity into crossbar; v2 smoke and README

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-25 11:12:24 -07:00
parent 47f49072cc
commit d0d3203f73
11 changed files with 300 additions and 71 deletions
+29
View File
@@ -69,6 +69,35 @@ func (p *Handler) guard(w http.ResponseWriter, r *http.Request, hosts []string,
return newHost, movedHeader(host, newHost), estimate, false
}
// Rule 4a: no host fits. Before refusing, ask a waker to rouse a candidate
// whose context may grow when it comes up; a woken host takes the lease.
if p.waker != nil {
for _, name := range hosts {
s, ok := p.health.Get(name)
if !ok {
continue
}
// A healthy host does not need waking; only a down host might grow
// a larger context when it comes up.
if s.Healthy {
continue
}
// A host with a known per-slot context smaller than the estimate
// cannot serve it no matter how it wakes.
if psc := s.PerSlotCtx(); psc != 0 && psc < estimate {
continue
}
if p.cfg.Hosts[name].Wake == nil || !p.waker.Wake(r.Context(), name) {
continue
}
if err := p.leases.Move(lease.Key{Route: route, FP: fp, Model: model}, name, time.Now()); err != nil {
p.writeError(w, http.StatusBadGateway, "upstream failed")
return host, "", estimate, true
}
return name, movedHeader(host, name), estimate, false
}
}
// Rule 4: no host fits. Answer 400 with the estimate and the largest
// available per-slot context, and record the row.
p.refuseCtx(w, host, route, model, fp, started, estimate, largestSlotCtx(hosts, p.health))