cache: Short TTL negative cache for 404/410 depot objects
CI / vulncheck (pull_request) Successful in 14s
CI / check-and-test (pull_request) Successful in 41s

Stop re-fetching gone depot objects on every miss: store 404/410 in the
existing VFS cache under the same key with a short TTL (default 5m).
This commit is contained in:
2026-09-08 16:40:03 +00:00
parent 8eb31143e5
commit 036ea1ea7f
10 changed files with 550 additions and 89 deletions
+21
View File
@@ -5,6 +5,7 @@ import (
"net"
"os"
"strings"
"time"
"github.com/docker/go-units"
"gopkg.in/yaml.v3"
@@ -35,6 +36,11 @@ type CacheConfig struct {
// Disk cache settings
Disk DiskConfig `yaml:"disk"`
// NegativeTTL is a Go duration string for cached 404/410 depot objects
// (same VFS key as a positive hit). Empty defaults to 5m. "0" disables
// storing negatives (the client still receives the upstream 404/410).
NegativeTTL string `yaml:"negative_ttl"`
}
type MemoryConfig struct {
@@ -100,6 +106,9 @@ func LoadConfig(configPath string) (*Config, error) {
if config.Cache.Disk.GCAlgorithm == "" {
config.Cache.Disk.GCAlgorithm = "lru"
}
if config.Cache.NegativeTTL == "" {
config.Cache.NegativeTTL = "5m"
}
return &config, nil
}
@@ -126,6 +135,7 @@ func SaveDefaultConfig(configPath string) error {
Path: "./disk",
GCAlgorithm: "lru", // Better for gaming patterns (keeps recently played games)
},
NegativeTTL: "5m",
},
Upstream: "",
}
@@ -162,6 +172,7 @@ func GetDefaultConfig() Config {
Path: "./disk",
GCAlgorithm: "lru",
},
NegativeTTL: "5m",
},
Upstream: "",
}
@@ -188,6 +199,16 @@ func (c Config) Validate() error {
return fmt.Errorf("disk cache enabled but no path specified")
}
if c.Cache.NegativeTTL != "" {
d, err := time.ParseDuration(c.Cache.NegativeTTL)
if err != nil {
return fmt.Errorf("invalid cache.negative_ttl: %w", err)
}
if d < 0 {
return fmt.Errorf("invalid cache.negative_ttl: negative duration")
}
}
// Light validation for security/resource fields (mirrors existing GC + path checks; fails fast before New)
if c.MaxObjectSize != "" && c.MaxObjectSize != "0" {
if _, err := units.FromHumanSize(c.MaxObjectSize); err != nil {