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
93 lines
2.1 KiB
Go
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
|
|
}
|