(tenant config.TenantConfig, req types.AIRequest, state types.RuntimeState)
| 51 | } |
| 52 | |
| 53 | func (r *RuleRouter) selectByRules(tenant config.TenantConfig, req types.AIRequest, state types.RuntimeState) (types.RouteDecision, error) { |
| 54 | _ = tenant |
| 55 | |
| 56 | for _, rule := range r.cfg.Routing.Rules { |
| 57 | if !matchesRule(rule, tenant, req) { |
| 58 | continue |
| 59 | } |
| 60 | |
| 61 | backend, ok := r.cfg.BackendByName(rule.UseBackend) |
| 62 | if !ok { |
| 63 | return types.RouteDecision{}, fmt.Errorf("rule %q references unknown backend %q", rule.Name, rule.UseBackend) |
| 64 | } |
| 65 | if !backendSelectable(state, backend.Name) { |
| 66 | continue |
| 67 | } |
| 68 | |
| 69 | return types.RouteDecision{ |
| 70 | BackendName: backend.Name, |
| 71 | Reason: rule.Name, |
| 72 | EstimatedCost: backend.Cost.Unit, |
| 73 | }, nil |
| 74 | } |
| 75 | |
| 76 | backend, ok := r.cfg.BackendByName(r.cfg.Routing.DefaultBackend) |
| 77 | if !ok { |
| 78 | return types.RouteDecision{}, fmt.Errorf("default backend %q not found", r.cfg.Routing.DefaultBackend) |
| 79 | } |
| 80 | if backendSelectable(state, backend.Name) { |
| 81 | return types.RouteDecision{ |
| 82 | BackendName: backend.Name, |
| 83 | Reason: "default-backend", |
| 84 | EstimatedCost: backend.Cost.Unit, |
| 85 | }, nil |
| 86 | } |
| 87 | |
| 88 | if d, ok := r.firstHealthyBackend(state); ok { |
| 89 | return d, nil |
| 90 | } |
| 91 | |
| 92 | return types.RouteDecision{}, fmt.Errorf("no healthy backend available") |
| 93 | } |
| 94 | |
| 95 | func (r *RuleRouter) firstHealthyBackend(state types.RuntimeState) (types.RouteDecision, bool) { |
| 96 | for _, backend := range r.cfg.Backends { |
no test coverage detected