Serve a cache hit with no database read or write (closes #309)
check / check (push) Canceled after 0s

A hit opens the variant file and nothing else: its content type comes
from the file's first bytes, and a file in no output format is a miss
and is made again. Its access time and hit count are handed, without
waiting, to the goroutine that wrote late counts, which now writes every
count and the access times once a second; the access times wait in a
channel of 10,000 that drops the rest. checkNegativeCache leaves expired
rows to CleanExpired. The .meta files, metaCache, Lookup and golang-lru
go, with their tests; tests that read counts after Get wait for the
background write. make bench runs a parallel cache hit benchmark,
outside make check.

Model: opus-5-5
This commit is contained in:
2026-10-21 15:10:31 +00:00
parent a19cca2f34
commit 83087db6a0
25 changed files with 963 additions and 1383 deletions
+9 -33
View File
@@ -2,7 +2,6 @@ package imgcache
import (
"context"
"encoding/json"
"io"
"os"
"testing"
@@ -552,10 +551,10 @@ func TestService_Get_Caching(t *testing.T) {
// a variant of it and sets back two days every time pixa stored for them.
// For the source: fetched_at and last_accessed_at in source_content, and the
// access and modification times of its file. For the variant: created_at and
// last_accessed_at in variant_content, the created_at in its .meta file, and
// the access and modification times of its file and of its .meta file. It
// then checks that the variant is still served from the cache and that a new
// variant is made from the cached source without fetching it again.
// last_accessed_at in variant_content, and the access and modification times
// of its file. It then checks that the variant is still served from the
// cache and that a new variant is made from the cached source without
// fetching it again.
//
// Left at the present: the files' status change and birth times, which a
// program cannot set, and the times of the directories holding the files,
@@ -598,6 +597,8 @@ func TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo(t *testing.T) {
_ = resp.Content.Close()
waitForPendingCountsWritten(t, svc.cache)
fetches := readCacheStatsCounters(t, svc.cache).upstreamFetchCount
if fetches != 1 {
t.Errorf("upstream fetches = %d, want 1", fetches)
@@ -636,41 +637,16 @@ func backdateVariant(
t.Helper()
key := imagerequest.CacheKey(req)
content, size, contentType, err := cache.variants.LoadWithMeta(key)
if err != nil || contentType == "" {
t.Fatalf("reading the variant's .meta file: content type %q, error %v",
contentType, err)
}
_ = content.Close()
meta, err := json.Marshal(VariantMeta{
ContentType: contentType,
Size: size,
CreatedAt: when.Unix(),
})
if err != nil {
t.Fatalf("encoding the variant's .meta file: %v", err)
}
path := cache.variants.keyToPath(key)
err = os.WriteFile(path+variantMetaSuffix, meta, StorageFilePerm)
if err != nil {
t.Fatalf("writing the variant's .meta file: %v", err)
}
updateOneRow(t, cache,
`UPDATE variant_content SET created_at = ? WHERE cache_key = ?`,
when.UTC().Format(sqliteTimestampFormat), string(key))
setVariantLastAccessed(t, cache, key, when)
for _, file := range []string{path, path + variantMetaSuffix} {
err = os.Chtimes(file, when, when)
if err != nil {
t.Fatalf("setting back the times of %s: %v", file, err)
}
err := os.Chtimes(path, when, when)
if err != nil {
t.Fatalf("setting back the times of %s: %v", path, err)
}
}