mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-11 17:47:20 +10:00
fix(ccm,ocm): restore fixed usage polling
Remove the poll_interval config surface from CCM and OCM so both services fall back to the built-in 1h polling cadence again. Also isolate CCM credential lock mocking per test instance so the access-token refresh tests stop racing on shared global state.
This commit is contained in:
@@ -104,8 +104,7 @@ A single OAuth credential file. The `type` field can be omitted (defaults to `de
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"strategy": "",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "60s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -113,7 +112,6 @@ Assigns sessions to default credentials based on the selected strategy. Sessions
|
||||
|
||||
- `strategy`: Selection strategy. One of `least_used` `round_robin` `random` `fallback`. `least_used` will be used by default.
|
||||
- `credentials`: ==Required== List of default credential tags.
|
||||
- `poll_interval`: How often to poll upstream usage API. Default `60s`.
|
||||
|
||||
##### Fallback Strategy
|
||||
|
||||
@@ -122,15 +120,13 @@ Assigns sessions to default credentials based on the selected strategy. Sessions
|
||||
"tag": "backup",
|
||||
"type": "balancer",
|
||||
"strategy": "fallback",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "30s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
A balancer with `strategy: "fallback"` uses credentials in order. It falls through to the next when the current one is exhausted.
|
||||
|
||||
- `credentials`: ==Required== Ordered list of default credential tags.
|
||||
- `poll_interval`: How often to poll upstream usage API. Default `60s`.
|
||||
|
||||
##### External Credential
|
||||
|
||||
@@ -144,8 +140,7 @@ A balancer with `strategy: "fallback"` uses credentials in order. It falls throu
|
||||
"token": "",
|
||||
"reverse": false,
|
||||
"detour": "",
|
||||
"usages_path": "",
|
||||
"poll_interval": "30m"
|
||||
"usages_path": ""
|
||||
}
|
||||
```
|
||||
|
||||
@@ -158,7 +153,6 @@ Proxies requests through a remote CCM instance instead of using a local OAuth cr
|
||||
- `reverse`: Enable connector mode. Requires `url`. A connector dials out to `/ccm/v1/reverse` on the remote instance and cannot serve local requests directly. When `url` is set without `reverse`, the credential proxies requests through the remote instance normally and prefers an established reverse connection when one is available.
|
||||
- `detour`: Outbound tag for connecting to the remote instance.
|
||||
- `usages_path`: Optional usage tracking file.
|
||||
- `poll_interval`: How often to poll the remote status endpoint. Default `30m`.
|
||||
|
||||
#### usages_path
|
||||
|
||||
@@ -290,7 +284,6 @@ claude
|
||||
{
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"poll_interval": "60s",
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -104,8 +104,7 @@ Claude Code OAuth 凭据文件的路径。
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"strategy": "",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "60s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -113,7 +112,6 @@ Claude Code OAuth 凭据文件的路径。
|
||||
|
||||
- `strategy`:选择策略。可选值:`least_used` `round_robin` `random` `fallback`。默认使用 `least_used`。
|
||||
- `credentials`:==必填== 默认凭据标签列表。
|
||||
- `poll_interval`:轮询上游使用 API 的间隔。默认 `60s`。
|
||||
|
||||
##### 回退策略
|
||||
|
||||
@@ -122,15 +120,13 @@ Claude Code OAuth 凭据文件的路径。
|
||||
"tag": "backup",
|
||||
"type": "balancer",
|
||||
"strategy": "fallback",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "30s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
将 `strategy` 设为 `fallback` 的均衡凭据会按顺序使用凭据。当前凭据耗尽后切换到下一个。
|
||||
|
||||
- `credentials`:==必填== 有序的默认凭据标签列表。
|
||||
- `poll_interval`:轮询上游使用 API 的间隔。默认 `60s`。
|
||||
|
||||
##### 外部凭据
|
||||
|
||||
@@ -144,8 +140,7 @@ Claude Code OAuth 凭据文件的路径。
|
||||
"token": "",
|
||||
"reverse": false,
|
||||
"detour": "",
|
||||
"usages_path": "",
|
||||
"poll_interval": "30m"
|
||||
"usages_path": ""
|
||||
}
|
||||
```
|
||||
|
||||
@@ -158,7 +153,6 @@ Claude Code OAuth 凭据文件的路径。
|
||||
- `reverse`:启用连接器模式。要求设置 `url`。启用后,此凭据会主动拨出到远程实例的 `/ccm/v1/reverse`,且不能直接为本地请求提供服务。当设置了 `url` 但未启用 `reverse` 时,此凭据会正常通过远程实例转发请求,并在反向连接建立后优先使用该反向连接。
|
||||
- `detour`:用于连接远程实例的出站标签。
|
||||
- `usages_path`:可选的使用跟踪文件。
|
||||
- `poll_interval`:轮询远程状态端点的间隔。默认 `30m`。
|
||||
|
||||
#### usages_path
|
||||
|
||||
@@ -290,7 +284,6 @@ claude
|
||||
{
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"poll_interval": "60s",
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -100,8 +100,7 @@ A single OAuth credential file. The `type` field can be omitted (defaults to `de
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"strategy": "",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "60s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -109,7 +108,6 @@ Assigns sessions to default credentials based on the selected strategy. Sessions
|
||||
|
||||
- `strategy`: Selection strategy. One of `least_used` `round_robin` `random` `fallback`. `least_used` will be used by default.
|
||||
- `credentials`: ==Required== List of default credential tags.
|
||||
- `poll_interval`: How often to poll upstream usage API. Default `60s`.
|
||||
|
||||
##### Fallback Strategy
|
||||
|
||||
@@ -118,15 +116,13 @@ Assigns sessions to default credentials based on the selected strategy. Sessions
|
||||
"tag": "backup",
|
||||
"type": "balancer",
|
||||
"strategy": "fallback",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "30s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
A balancer with `strategy: "fallback"` uses credentials in order. It falls through to the next when the current one is exhausted.
|
||||
|
||||
- `credentials`: ==Required== Ordered list of default credential tags.
|
||||
- `poll_interval`: How often to poll upstream usage API. Default `60s`.
|
||||
|
||||
##### External Credential
|
||||
|
||||
@@ -140,8 +136,7 @@ A balancer with `strategy: "fallback"` uses credentials in order. It falls throu
|
||||
"token": "",
|
||||
"reverse": false,
|
||||
"detour": "",
|
||||
"usages_path": "",
|
||||
"poll_interval": "30m"
|
||||
"usages_path": ""
|
||||
}
|
||||
```
|
||||
|
||||
@@ -154,7 +149,6 @@ Proxies requests through a remote OCM instance instead of using a local OAuth cr
|
||||
- `reverse`: Enable connector mode. Requires `url`. A connector dials out to `/ocm/v1/reverse` on the remote instance and cannot serve local requests directly. When `url` is set without `reverse`, the credential proxies requests through the remote instance normally and prefers an established reverse connection when one is available.
|
||||
- `detour`: Outbound tag for connecting to the remote instance.
|
||||
- `usages_path`: Optional usage tracking file.
|
||||
- `poll_interval`: How often to poll the remote status endpoint. Default `30m`.
|
||||
|
||||
#### usages_path
|
||||
|
||||
@@ -342,7 +336,6 @@ codex --profile ocm
|
||||
{
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"poll_interval": "60s",
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -100,8 +100,7 @@ OpenAI OAuth 凭据文件的路径。
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"strategy": "",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "60s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -109,7 +108,6 @@ OpenAI OAuth 凭据文件的路径。
|
||||
|
||||
- `strategy`:选择策略。可选值:`least_used` `round_robin` `random` `fallback`。默认使用 `least_used`。
|
||||
- `credentials`:==必填== 默认凭据标签列表。
|
||||
- `poll_interval`:轮询上游使用 API 的间隔。默认 `60s`。
|
||||
|
||||
##### 回退策略
|
||||
|
||||
@@ -118,15 +116,13 @@ OpenAI OAuth 凭据文件的路径。
|
||||
"tag": "backup",
|
||||
"type": "balancer",
|
||||
"strategy": "fallback",
|
||||
"credentials": ["a", "b"],
|
||||
"poll_interval": "30s"
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
```
|
||||
|
||||
将 `strategy` 设为 `fallback` 的均衡凭据会按顺序使用凭据。当前凭据耗尽后切换到下一个。
|
||||
|
||||
- `credentials`:==必填== 有序的默认凭据标签列表。
|
||||
- `poll_interval`:轮询上游使用 API 的间隔。默认 `60s`。
|
||||
|
||||
##### 外部凭据
|
||||
|
||||
@@ -140,8 +136,7 @@ OpenAI OAuth 凭据文件的路径。
|
||||
"token": "",
|
||||
"reverse": false,
|
||||
"detour": "",
|
||||
"usages_path": "",
|
||||
"poll_interval": "30m"
|
||||
"usages_path": ""
|
||||
}
|
||||
```
|
||||
|
||||
@@ -154,7 +149,6 @@ OpenAI OAuth 凭据文件的路径。
|
||||
- `reverse`:启用连接器模式。要求设置 `url`。启用后,此凭据会主动拨出到远程实例的 `/ocm/v1/reverse`,且不能直接为本地请求提供服务。当设置了 `url` 但未启用 `reverse` 时,此凭据会正常通过远程实例转发请求,并在反向连接建立后优先使用该反向连接。
|
||||
- `detour`:用于连接远程实例的出站标签。
|
||||
- `usages_path`:可选的使用跟踪文件。
|
||||
- `poll_interval`:轮询远程状态端点的间隔。默认 `30m`。
|
||||
|
||||
#### usages_path
|
||||
|
||||
@@ -343,7 +337,6 @@ codex --profile ocm
|
||||
{
|
||||
"tag": "pool",
|
||||
"type": "balancer",
|
||||
"poll_interval": "60s",
|
||||
"credentials": ["a", "b"]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -89,16 +89,14 @@ type CCMDefaultCredentialOptions struct {
|
||||
type CCMBalancerCredentialOptions struct {
|
||||
Strategy string `json:"strategy,omitempty"`
|
||||
Credentials badoption.Listable[string] `json:"credentials"`
|
||||
PollInterval badoption.Duration `json:"poll_interval,omitempty"`
|
||||
RebalanceThreshold float64 `json:"rebalance_threshold,omitempty"`
|
||||
}
|
||||
|
||||
type CCMExternalCredentialOptions struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
ServerOptions
|
||||
Token string `json:"token"`
|
||||
Reverse bool `json:"reverse,omitempty"`
|
||||
Detour string `json:"detour,omitempty"`
|
||||
UsagesPath string `json:"usages_path,omitempty"`
|
||||
PollInterval badoption.Duration `json:"poll_interval,omitempty"`
|
||||
Token string `json:"token"`
|
||||
Reverse bool `json:"reverse,omitempty"`
|
||||
Detour string `json:"detour,omitempty"`
|
||||
UsagesPath string `json:"usages_path,omitempty"`
|
||||
}
|
||||
|
||||
@@ -88,16 +88,14 @@ type OCMDefaultCredentialOptions struct {
|
||||
type OCMBalancerCredentialOptions struct {
|
||||
Strategy string `json:"strategy,omitempty"`
|
||||
Credentials badoption.Listable[string] `json:"credentials"`
|
||||
PollInterval badoption.Duration `json:"poll_interval,omitempty"`
|
||||
RebalanceThreshold float64 `json:"rebalance_threshold,omitempty"`
|
||||
}
|
||||
|
||||
type OCMExternalCredentialOptions struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
ServerOptions
|
||||
Token string `json:"token"`
|
||||
Reverse bool `json:"reverse,omitempty"`
|
||||
Detour string `json:"detour,omitempty"`
|
||||
UsagesPath string `json:"usages_path,omitempty"`
|
||||
PollInterval badoption.Duration `json:"poll_interval,omitempty"`
|
||||
Token string `json:"token"`
|
||||
Reverse bool `json:"reverse,omitempty"`
|
||||
Detour string `json:"detour,omitempty"`
|
||||
UsagesPath string `json:"usages_path,omitempty"`
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package ccm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
@@ -48,7 +47,7 @@ func buildCredentialProviders(
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
providers[credentialOption.Tag] = newBalancerProvider(subCredentials, credentialOption.BalancerOptions.Strategy, time.Duration(credentialOption.BalancerOptions.PollInterval), credentialOption.BalancerOptions.RebalanceThreshold, logger)
|
||||
providers[credentialOption.Tag] = newBalancerProvider(subCredentials, credentialOption.BalancerOptions.Strategy, credentialOption.BalancerOptions.RebalanceThreshold, logger)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ import (
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
)
|
||||
|
||||
var acquireCredentialLockFunc = acquireCredentialLock
|
||||
|
||||
type claudeProfileSnapshot struct {
|
||||
OAuthAccount *claudeOAuthAccount
|
||||
AccountType string
|
||||
@@ -56,6 +54,7 @@ type defaultCredential struct {
|
||||
capWeekly float64
|
||||
usageTracker *AggregatedUsage
|
||||
forwardHTTPClient *http.Client
|
||||
acquireLock func(string) (func(), error)
|
||||
logger log.ContextLogger
|
||||
watcher *fswatch.Watcher
|
||||
watcherRetryAt time.Time
|
||||
@@ -122,6 +121,7 @@ func newDefaultCredential(ctx context.Context, tag string, options option.CCMDef
|
||||
cap5h: cap5h,
|
||||
capWeekly: capWeekly,
|
||||
forwardHTTPClient: httpClient,
|
||||
acquireLock: acquireCredentialLock,
|
||||
logger: logger,
|
||||
requestContext: requestContext,
|
||||
cancelRequests: cancelRequests,
|
||||
@@ -363,7 +363,11 @@ func (c *defaultCredential) tryRefreshCredentials(force bool) bool {
|
||||
if !c.shouldAttemptRefresh(currentCredentials, force) {
|
||||
return false
|
||||
}
|
||||
release, err := acquireCredentialLockFunc(c.configDir)
|
||||
acquireLock := c.acquireLock
|
||||
if acquireLock == nil {
|
||||
acquireLock = acquireCredentialLock
|
||||
}
|
||||
release, err := acquireLock(c.configDir)
|
||||
if err != nil {
|
||||
c.logger.Debug("acquire credential lock for ", c.tag, ": ", err)
|
||||
return false
|
||||
|
||||
@@ -31,13 +31,9 @@ func TestGetAccessTokenReturnsExistingTokenWhenLockFails(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
originalLockFunc := acquireCredentialLockFunc
|
||||
acquireCredentialLockFunc = func(string) (func(), error) {
|
||||
credential.acquireLock = func(string) (func(), error) {
|
||||
return nil, errors.New("locked")
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
acquireCredentialLockFunc = originalLockFunc
|
||||
})
|
||||
|
||||
token, err := credential.getAccessToken()
|
||||
if err != nil {
|
||||
|
||||
@@ -38,7 +38,6 @@ type externalCredential struct {
|
||||
state credentialState
|
||||
stateAccess sync.RWMutex
|
||||
pollAccess sync.Mutex
|
||||
pollInterval time.Duration
|
||||
usageTracker *AggregatedUsage
|
||||
logger log.ContextLogger
|
||||
|
||||
@@ -113,18 +112,12 @@ func externalCredentialReversePath(parsedURL *url.URL, endpointPath string) stri
|
||||
}
|
||||
|
||||
func newExternalCredential(ctx context.Context, tag string, options option.CCMExternalCredentialOptions, logger log.ContextLogger) (*externalCredential, error) {
|
||||
pollInterval := time.Duration(options.PollInterval)
|
||||
if pollInterval <= 0 {
|
||||
pollInterval = 30 * time.Minute
|
||||
}
|
||||
|
||||
requestContext, cancelRequests := context.WithCancel(context.Background())
|
||||
reverseContext, reverseCancel := context.WithCancel(context.Background())
|
||||
|
||||
credential := &externalCredential{
|
||||
tag: tag,
|
||||
token: options.Token,
|
||||
pollInterval: pollInterval,
|
||||
logger: logger,
|
||||
requestContext: requestContext,
|
||||
cancelRequests: cancelRequests,
|
||||
@@ -355,9 +348,9 @@ func (c *externalCredential) markRateLimited(resetAt time.Time) {
|
||||
}
|
||||
|
||||
func (c *externalCredential) markUpstreamRejected() {
|
||||
c.logger.Warn("upstream rejected credential ", c.tag, ", marking unavailable for ", log.FormatDuration(c.pollInterval))
|
||||
c.logger.Warn("upstream rejected credential ", c.tag, ", marking unavailable for ", log.FormatDuration(defaultPollInterval))
|
||||
c.stateAccess.Lock()
|
||||
c.state.upstreamRejectedUntil = time.Now().Add(c.pollInterval)
|
||||
c.state.upstreamRejectedUntil = time.Now().Add(defaultPollInterval)
|
||||
c.state.setAvailability(availabilityStateTemporarilyBlocked, availabilityReasonUpstreamRejected, c.state.upstreamRejectedUntil)
|
||||
shouldInterrupt := c.checkTransitionLocked()
|
||||
c.stateAccess.Unlock()
|
||||
|
||||
@@ -112,7 +112,6 @@ type balancerProvider struct {
|
||||
credentials []Credential
|
||||
strategy string
|
||||
roundRobinIndex atomic.Uint64
|
||||
pollInterval time.Duration
|
||||
rebalanceThreshold float64
|
||||
sessionAccess sync.RWMutex
|
||||
sessions map[string]sessionEntry
|
||||
@@ -121,14 +120,10 @@ type balancerProvider struct {
|
||||
logger log.ContextLogger
|
||||
}
|
||||
|
||||
func newBalancerProvider(credentials []Credential, strategy string, pollInterval time.Duration, rebalanceThreshold float64, logger log.ContextLogger) *balancerProvider {
|
||||
if pollInterval <= 0 {
|
||||
pollInterval = defaultPollInterval
|
||||
}
|
||||
func newBalancerProvider(credentials []Credential, strategy string, rebalanceThreshold float64, logger log.ContextLogger) *balancerProvider {
|
||||
return &balancerProvider{
|
||||
credentials: credentials,
|
||||
strategy: strategy,
|
||||
pollInterval: pollInterval,
|
||||
rebalanceThreshold: rebalanceThreshold,
|
||||
sessions: make(map[string]sessionEntry),
|
||||
credentialInterrupts: make(map[credentialInterruptKey]credentialInterruptEntry),
|
||||
@@ -383,14 +378,14 @@ func (p *balancerProvider) pollIfStale() {
|
||||
p.interruptAccess.Unlock()
|
||||
|
||||
for _, credential := range p.credentials {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(p.pollInterval) {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(defaultPollInterval) {
|
||||
credential.pollUsage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *balancerProvider) pollCredentialIfStale(credential Credential) {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(p.pollInterval) {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(defaultPollInterval) {
|
||||
credential.pollUsage()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ func newTestDefaultCredential(t *testing.T, credentialPath string, transport htt
|
||||
cap5h: 99,
|
||||
capWeekly: 99,
|
||||
forwardHTTPClient: &http.Client{Transport: transport},
|
||||
acquireLock: acquireCredentialLock,
|
||||
logger: log.NewNOPFactory().Logger(),
|
||||
requestContext: requestContext,
|
||||
cancelRequests: cancelRequests,
|
||||
|
||||
@@ -2,7 +2,6 @@ package ocm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
@@ -48,7 +47,7 @@ func buildOCMCredentialProviders(
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
providers[credentialOption.Tag] = newBalancerProvider(subCredentials, credentialOption.BalancerOptions.Strategy, time.Duration(credentialOption.BalancerOptions.PollInterval), credentialOption.BalancerOptions.RebalanceThreshold, logger)
|
||||
providers[credentialOption.Tag] = newBalancerProvider(subCredentials, credentialOption.BalancerOptions.Strategy, credentialOption.BalancerOptions.RebalanceThreshold, logger)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ type externalCredential struct {
|
||||
state credentialState
|
||||
stateAccess sync.RWMutex
|
||||
pollAccess sync.Mutex
|
||||
pollInterval time.Duration
|
||||
usageTracker *AggregatedUsage
|
||||
logger log.ContextLogger
|
||||
|
||||
@@ -131,18 +130,12 @@ func externalCredentialReversePath(parsedURL *url.URL, endpointPath string) stri
|
||||
}
|
||||
|
||||
func newExternalCredential(ctx context.Context, tag string, options option.OCMExternalCredentialOptions, logger log.ContextLogger) (*externalCredential, error) {
|
||||
pollInterval := time.Duration(options.PollInterval)
|
||||
if pollInterval <= 0 {
|
||||
pollInterval = 30 * time.Minute
|
||||
}
|
||||
|
||||
requestContext, cancelRequests := context.WithCancel(context.Background())
|
||||
reverseContext, reverseCancel := context.WithCancel(context.Background())
|
||||
|
||||
credential := &externalCredential{
|
||||
tag: tag,
|
||||
token: options.Token,
|
||||
pollInterval: pollInterval,
|
||||
logger: logger,
|
||||
requestContext: requestContext,
|
||||
cancelRequests: cancelRequests,
|
||||
@@ -377,9 +370,9 @@ func (c *externalCredential) markRateLimited(resetAt time.Time) {
|
||||
}
|
||||
|
||||
func (c *externalCredential) markUpstreamRejected() {
|
||||
c.logger.Warn("upstream rejected credential ", c.tag, ", marking unavailable for ", log.FormatDuration(c.pollInterval))
|
||||
c.logger.Warn("upstream rejected credential ", c.tag, ", marking unavailable for ", log.FormatDuration(defaultPollInterval))
|
||||
c.stateAccess.Lock()
|
||||
c.state.upstreamRejectedUntil = time.Now().Add(c.pollInterval)
|
||||
c.state.upstreamRejectedUntil = time.Now().Add(defaultPollInterval)
|
||||
c.state.setAvailability(availabilityStateTemporarilyBlocked, availabilityReasonUpstreamRejected, c.state.upstreamRejectedUntil)
|
||||
shouldInterrupt := c.checkTransitionLocked()
|
||||
c.stateAccess.Unlock()
|
||||
|
||||
@@ -112,7 +112,6 @@ type balancerProvider struct {
|
||||
credentials []Credential
|
||||
strategy string
|
||||
roundRobinIndex atomic.Uint64
|
||||
pollInterval time.Duration
|
||||
rebalanceThreshold float64
|
||||
sessionAccess sync.RWMutex
|
||||
sessions map[string]sessionEntry
|
||||
@@ -125,14 +124,10 @@ func compositeCredentialSelectable(credential Credential) bool {
|
||||
return !credential.ocmIsAPIKeyMode()
|
||||
}
|
||||
|
||||
func newBalancerProvider(credentials []Credential, strategy string, pollInterval time.Duration, rebalanceThreshold float64, logger log.ContextLogger) *balancerProvider {
|
||||
if pollInterval <= 0 {
|
||||
pollInterval = defaultPollInterval
|
||||
}
|
||||
func newBalancerProvider(credentials []Credential, strategy string, rebalanceThreshold float64, logger log.ContextLogger) *balancerProvider {
|
||||
return &balancerProvider{
|
||||
credentials: credentials,
|
||||
strategy: strategy,
|
||||
pollInterval: pollInterval,
|
||||
rebalanceThreshold: rebalanceThreshold,
|
||||
sessions: make(map[string]sessionEntry),
|
||||
credentialInterrupts: make(map[credentialInterruptKey]credentialInterruptEntry),
|
||||
@@ -410,14 +405,14 @@ func (p *balancerProvider) pollIfStale() {
|
||||
p.interruptAccess.Unlock()
|
||||
|
||||
for _, credential := range p.credentials {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(p.pollInterval) {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(defaultPollInterval) {
|
||||
credential.pollUsage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *balancerProvider) pollCredentialIfStale(credential Credential) {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(p.pollInterval) {
|
||||
if time.Since(credential.lastUpdatedTime()) > credential.pollBackoff(defaultPollInterval) {
|
||||
credential.pollUsage()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user