Files
tutti/services/tuttid/service/agent/provider_availability_cache.go
T
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

93 lines
2.1 KiB
Go

package agent
import (
"strings"
"sync"
"time"
)
const defaultProviderAvailabilityCacheTTL = 30 * time.Minute
type providerAvailabilityCache struct {
mu sync.Mutex
entries map[string]providerAvailabilityCacheEntry
}
type providerAvailabilityCacheEntry struct {
cachedAt time.Time
availability []ProviderAvailability
}
func newProviderAvailabilityCache() *providerAvailabilityCache {
return &providerAvailabilityCache{
entries: make(map[string]providerAvailabilityCacheEntry),
}
}
func (c *providerAvailabilityCache) get(key string, now time.Time, ttl time.Duration) ([]ProviderAvailability, bool) {
if c == nil || ttl <= 0 {
return nil, false
}
c.mu.Lock()
defer c.mu.Unlock()
entry, ok := c.entries[key]
if !ok {
return nil, false
}
if now.Sub(entry.cachedAt) > ttl {
delete(c.entries, key)
return nil, false
}
return cloneProviderAvailability(entry.availability), true
}
func (c *providerAvailabilityCache) set(key string, now time.Time, availability []ProviderAvailability) {
if c == nil {
return
}
c.mu.Lock()
defer c.mu.Unlock()
c.entries[key] = providerAvailabilityCacheEntry{
cachedAt: now,
availability: cloneProviderAvailability(availability),
}
}
func (c *providerAvailabilityCache) invalidate(provider string) {
if c == nil {
return
}
provider = strings.TrimSpace(provider)
c.mu.Lock()
defer c.mu.Unlock()
delete(c.entries, providerAvailabilityCacheKey(nil))
if provider != "" {
delete(c.entries, providerAvailabilityCacheKey([]string{provider}))
}
}
func providerAvailabilityCacheKey(providers []string) string {
if len(providers) == 0 {
return "<all>"
}
return strings.Join(providers, "\x00")
}
func cloneProviderAvailability(items []ProviderAvailability) []ProviderAvailability {
if len(items) == 0 {
return nil
}
result := make([]ProviderAvailability, len(items))
for i, item := range items {
result[i] = item
if len(item.Checks) > 0 {
result[i].Checks = append([]ProviderAvailabilityCheck(nil), item.Checks...)
}
if item.LastError != nil {
errorCopy := *item.LastError
result[i].LastError = &errorCopy
}
}
return result
}