cache: Short TTL negative cache for 404/410 depot objects
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:
@@ -59,6 +59,10 @@ type SteamCache struct {
|
||||
maxObjectSize int64
|
||||
trustedProxies []string
|
||||
|
||||
// Negative TTL for 404/410 depot objects stored in the same VFS cache.
|
||||
// Zero disables storing negatives (client still receives the upstream status).
|
||||
negativeTTL time.Duration
|
||||
|
||||
// Service management
|
||||
serviceManager *ServiceManager
|
||||
|
||||
@@ -71,14 +75,17 @@ type SteamCache struct {
|
||||
processor *requestProcessor
|
||||
}
|
||||
|
||||
// DefaultNegativeTTL is used when cache.negative_ttl / Options.NegativeTTL is empty.
|
||||
const DefaultNegativeTTL = 5 * time.Minute
|
||||
|
||||
// New creates a new SteamCache instance.
|
||||
// Returns an error (instead of panicking) on invalid memorySize or diskSize strings.
|
||||
// Also validates maxObjectSize and accepts trustedProxies for X-Forwarded-For handling.
|
||||
// Empty maxObjectSize or nil trustedProxies are normalized to safe defaults before parsing.
|
||||
// negativeTTL is a Go duration string for 404/410 negative cache entries; empty means 5m.
|
||||
// Callers must check the returned error.
|
||||
// The two new positional parameters are a breaking change for direct importers of the simple constructor.
|
||||
// Prefer NewWithOptions (or config file) for forward compatibility. See README migration notes.
|
||||
func New(address string, memorySize string, diskSize string, diskPath, upstream, memoryGC, diskGC string, maxConcurrentRequests int64, maxRequestsPerClient int64, maxObjectSize string, trustedProxies []string) (*SteamCache, error) {
|
||||
func New(address string, memorySize string, diskSize string, diskPath, upstream, memoryGC, diskGC string, maxConcurrentRequests int64, maxRequestsPerClient int64, maxObjectSize string, trustedProxies []string, negativeTTL string) (*SteamCache, error) {
|
||||
memorysize, err := units.FromHumanSize(memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid memory size: %w", err)
|
||||
@@ -102,6 +109,11 @@ func New(address string, memorySize string, diskSize string, diskPath, upstream,
|
||||
return nil, fmt.Errorf("invalid max object size: %w", err)
|
||||
}
|
||||
|
||||
negTTL, err := parseNegativeTTL(negativeTTL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := cache.New()
|
||||
|
||||
var m *memory.MemoryFS
|
||||
@@ -171,6 +183,7 @@ func New(address string, memorySize string, diskSize string, diskPath, upstream,
|
||||
// Hardening config plumbed
|
||||
maxObjectSize: maxObjBytes,
|
||||
trustedProxies: trustedProxies,
|
||||
negativeTTL: negTTL,
|
||||
|
||||
// Initialize service management
|
||||
serviceManager: NewServiceManager(),
|
||||
@@ -352,6 +365,26 @@ func (sc *SteamCache) ResetMetrics() {
|
||||
sc.metrics.Reset()
|
||||
}
|
||||
|
||||
// parseNegativeTTL parses a Go duration string for 404/410 negative cache entries.
|
||||
// Empty means DefaultNegativeTTL. Zero disables storing negatives.
|
||||
func parseNegativeTTL(s string) (time.Duration, error) {
|
||||
if s == "" {
|
||||
return DefaultNegativeTTL, nil
|
||||
}
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid negative ttl: %w", err)
|
||||
}
|
||||
if d < 0 {
|
||||
return 0, fmt.Errorf("invalid negative ttl: negative duration")
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func isDefinitiveGone(statusCode int) bool {
|
||||
return statusCode == http.StatusNotFound || statusCode == http.StatusGone
|
||||
}
|
||||
|
||||
// newHTTPTransport returns a tuned http.Transport for upstream fetches.
|
||||
// Extracted to shrink New (Phase 3).
|
||||
func newHTTPTransport() *http.Transport {
|
||||
|
||||
Reference in New Issue
Block a user