package slurm import ( "context" "sync" "time" ) type TokenCache struct { mu sync.RWMutex token string expireAt time.Time refresh func(ctx context.Context) (string, error) ttl time.Duration leeway time.Duration } func NewTokenCache(refresh func(ctx context.Context) (string, error), ttl time.Duration, leeway time.Duration) *TokenCache { return &TokenCache{ refresh: refresh, ttl: ttl, leeway: leeway, } } func (c *TokenCache) Token(ctx context.Context) (string, error) { c.mu.RLock() if c.token != "" && time.Now().Before(c.expireAt.Add(-c.leeway)) { token := c.token c.mu.RUnlock() return token, nil } c.mu.RUnlock() c.mu.Lock() defer c.mu.Unlock() if c.token != "" && time.Now().Before(c.expireAt.Add(-c.leeway)) { return c.token, nil } token, err := c.refresh(ctx) if err != nil { return "", err } c.token = token c.expireAt = time.Now().Add(c.ttl) return token, nil }