cache: Serve Range GET from disk when present
Steam clients lean on Range requests. Hit/miss looked fine while downloads still felt cold when a Range miss returned the full upstream body as 200. Add range_cache / range_upstream metrics. HIT path already sliced 206 from the cached full object; count range_cache there. On MISS, keep stripping Range for the upstream fetch (full object still cached) but serve the client's requested slice as 206 and count range_upstream. Tests in steamcache/range_test.go cover Range HIT (local, no upstream), Range MISS (206 + full object cached), and /metrics emission.
This commit is contained in:
@@ -16,6 +16,8 @@ type Metrics struct {
|
||||
CacheHits int64
|
||||
CacheMisses int64
|
||||
CacheCoalesced int64
|
||||
RangeCache int64 // Range requests served as 206 from an already-cached object (HIT)
|
||||
RangeUpstream int64 // Range requests that required an upstream fetch (full object), served as 206
|
||||
Errors int64
|
||||
RateLimited int64
|
||||
|
||||
@@ -78,6 +80,17 @@ func (m *Metrics) IncrementCacheCoalesced() {
|
||||
atomic.AddInt64(&m.CacheCoalesced, 1)
|
||||
}
|
||||
|
||||
// IncrementRangeCache increments the Range-from-cache counter (HIT served as 206)
|
||||
func (m *Metrics) IncrementRangeCache() {
|
||||
atomic.AddInt64(&m.RangeCache, 1)
|
||||
}
|
||||
|
||||
// IncrementRangeUpstream increments the Range-from-upstream counter (full object
|
||||
// fetched upstream, requested slice served as 206)
|
||||
func (m *Metrics) IncrementRangeUpstream() {
|
||||
atomic.AddInt64(&m.RangeUpstream, 1)
|
||||
}
|
||||
|
||||
// IncrementErrors increments the error counter
|
||||
func (m *Metrics) IncrementErrors() {
|
||||
atomic.AddInt64(&m.Errors, 1)
|
||||
@@ -188,6 +201,8 @@ func (m *Metrics) GetStats() *Stats {
|
||||
CacheHits: cacheHits,
|
||||
CacheMisses: cacheMisses,
|
||||
CacheCoalesced: atomic.LoadInt64(&m.CacheCoalesced),
|
||||
RangeCache: atomic.LoadInt64(&m.RangeCache),
|
||||
RangeUpstream: atomic.LoadInt64(&m.RangeUpstream),
|
||||
Errors: atomic.LoadInt64(&m.Errors),
|
||||
RateLimited: atomic.LoadInt64(&m.RateLimited),
|
||||
HitRate: hitRate,
|
||||
@@ -215,6 +230,8 @@ func (m *Metrics) Reset() {
|
||||
atomic.StoreInt64(&m.CacheHits, 0)
|
||||
atomic.StoreInt64(&m.CacheMisses, 0)
|
||||
atomic.StoreInt64(&m.CacheCoalesced, 0)
|
||||
atomic.StoreInt64(&m.RangeCache, 0)
|
||||
atomic.StoreInt64(&m.RangeUpstream, 0)
|
||||
atomic.StoreInt64(&m.Errors, 0)
|
||||
atomic.StoreInt64(&m.RateLimited, 0)
|
||||
atomic.StoreInt64(&m.TotalResponseTime, 0)
|
||||
@@ -244,6 +261,8 @@ type Stats struct {
|
||||
CacheHits int64
|
||||
CacheMisses int64
|
||||
CacheCoalesced int64
|
||||
RangeCache int64
|
||||
RangeUpstream int64
|
||||
Errors int64
|
||||
RateLimited int64
|
||||
HitRate float64
|
||||
@@ -276,6 +295,8 @@ func WriteText(w http.ResponseWriter, stats *Stats) {
|
||||
_, _ = fmt.Fprintf(w, "cache_hits %d\n", stats.CacheHits)
|
||||
_, _ = fmt.Fprintf(w, "cache_misses %d\n", stats.CacheMisses)
|
||||
_, _ = fmt.Fprintf(w, "cache_coalesced %d\n", stats.CacheCoalesced)
|
||||
_, _ = fmt.Fprintf(w, "range_cache %d\n", stats.RangeCache)
|
||||
_, _ = fmt.Fprintf(w, "range_upstream %d\n", stats.RangeUpstream)
|
||||
_, _ = fmt.Fprintf(w, "errors %d\n", stats.Errors)
|
||||
_, _ = fmt.Fprintf(w, "rate_limited %d\n", stats.RateLimited)
|
||||
_, _ = fmt.Fprintf(w, "upstream_errors %d\n", stats.UpstreamErrors)
|
||||
|
||||
Reference in New Issue
Block a user