feat(v2): limit_aware 策略(UsageSource 留位)+ Router 按配置派发 + config.Routing
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
package accounts
|
||||
|
||||
import "github.com/wangjia/pay/config"
|
||||
|
||||
// Router 是 gateway 面向的 Picker 实现:取候选(EnabledFor)→ 按 hint 排除 → 派发策略。
|
||||
// 策略实例进程内单例(round_robin 计数器需长存);未配置/未知策略默认 round_robin。
|
||||
type Router struct {
|
||||
reg *Registry
|
||||
strategies map[string]string // channel -> 策略名
|
||||
byName map[string]Strategy
|
||||
def Strategy
|
||||
}
|
||||
|
||||
// NewRouter 装配路由。routing:channel→策略名(缺省/未知→round_robin);usage=nil→NopUsage。
|
||||
// limit_aware 复合 round_robin 作为合格集内的均摊基础策略。
|
||||
func NewRouter(reg *Registry, routing map[string]string, usage UsageSource) *Router {
|
||||
rr := NewRoundRobin()
|
||||
byName := map[string]Strategy{
|
||||
StrategyRoundRobin: rr,
|
||||
StrategyWeighted: NewWeighted(),
|
||||
StrategyLimitAware: NewLimitAware(rr, usage),
|
||||
}
|
||||
cp := map[string]string{}
|
||||
for k, v := range routing {
|
||||
cp[k] = v
|
||||
}
|
||||
return &Router{reg: reg, strategies: cp, byName: byName, def: rr}
|
||||
}
|
||||
|
||||
func (r *Router) strategyFor(channel string) Strategy {
|
||||
if name, ok := r.strategies[channel]; ok {
|
||||
if s, ok := r.byName[name]; ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return r.def // 缺省 / 未知策略名 → round_robin(见计划 D3)
|
||||
}
|
||||
|
||||
// Pick 实现 accounts.Picker。
|
||||
func (r *Router) Pick(channel, region string, hint PickHint) (config.AccountConfig, error) {
|
||||
cands := r.reg.EnabledFor(channel, region)
|
||||
if len(cands) == 0 {
|
||||
return config.AccountConfig{}, ErrNoAccount
|
||||
}
|
||||
if len(hint.ExcludeAccounts) > 0 {
|
||||
if filtered := excludeAccounts(cands, hint.ExcludeAccounts); len(filtered) > 0 {
|
||||
cands = filtered // 过滤到空则保留全集:单账户渠道 retry 仍可用(见计划 D4)
|
||||
}
|
||||
}
|
||||
return r.strategyFor(channel).Pick(channel+"|"+region, cands, hint)
|
||||
}
|
||||
|
||||
func excludeAccounts(cands []config.AccountConfig, exclude []string) []config.AccountConfig {
|
||||
skip := make(map[string]struct{}, len(exclude))
|
||||
for _, id := range exclude {
|
||||
skip[id] = struct{}{}
|
||||
}
|
||||
out := make([]config.AccountConfig, 0, len(cands))
|
||||
for _, c := range cands {
|
||||
if _, ok := skip[c.AccountID]; ok {
|
||||
continue
|
||||
}
|
||||
out = append(out, c)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user