refactor: propagate context into Cache.StoreVariant (noctx)

The size-accounting INSERT in StoreVariant used db.Exec, and
StoreVariant took no context at all, so the write was uncancellable and
untraceable. Rather than paper over that with context.Background() at
the call site, StoreVariant now takes a context.Context and uses
ExecContext.

The plumbing is small: the only production caller is
Service.processAndStore, which already has the request context in
scope, so the accounting insert now shares the lifetime of the request
that produced the variant. Test callers pass t.Context().

The insert remains best-effort: a failure is logged and the startup and
periodic reconciliation passes still adopt any variant file whose
accounting row is missing.
This commit is contained in:
2026-08-09 13:37:12 +00:00
parent 9218d7e7f6
commit 061a3545eb
4 changed files with 13 additions and 9 deletions

View File

@@ -291,7 +291,7 @@ func (c *Cache) StoreSource(
// accounting insert is best-effort (the startup reconciliation pass // accounting insert is best-effort (the startup reconciliation pass
// adopts any variant file that misses its accounting row). // adopts any variant file that misses its accounting row).
func (c *Cache) StoreVariant( func (c *Cache) StoreVariant(
cacheKey VariantKey, content io.Reader, contentType string, ctx context.Context, cacheKey VariantKey, content io.Reader, contentType string,
) error { ) error {
if c.disabled { if c.disabled {
return nil return nil
@@ -302,7 +302,7 @@ func (c *Cache) StoreVariant(
return err return err
} }
_, err = c.db.Exec(` _, err = c.db.ExecContext(ctx, `
INSERT INTO variant_content (cache_key, size_bytes, content_type) INSERT INTO variant_content (cache_key, size_bytes, content_type)
VALUES (?, ?, ?) VALUES (?, ?, ?)
ON CONFLICT(cache_key) DO UPDATE SET ON CONFLICT(cache_key) DO UPDATE SET

View File

@@ -177,7 +177,8 @@ func TestCache_StoreAndLookup(t *testing.T) {
cacheKey := CacheKey(req) cacheKey := CacheKey(req)
outputContent := []byte("fake webp data") outputContent := []byte("fake webp data")
err = cache.StoreVariant(cacheKey, bytes.NewReader(outputContent), "image/webp") err = cache.StoreVariant(
t.Context(), cacheKey, bytes.NewReader(outputContent), "image/webp")
if err != nil { if err != nil {
t.Fatalf("StoreVariant() error = %v", err) t.Fatalf("StoreVariant() error = %v", err)
} }
@@ -295,7 +296,8 @@ func TestCache_VariantLookup(t *testing.T) {
cacheKey := CacheKey(req) cacheKey := CacheKey(req)
outputContent := []byte("output data") outputContent := []byte("output data")
err := cache.StoreVariant(cacheKey, bytes.NewReader(outputContent), "image/webp") err := cache.StoreVariant(
t.Context(), cacheKey, bytes.NewReader(outputContent), "image/webp")
if err != nil { if err != nil {
t.Fatalf("StoreVariant() error = %v", err) t.Fatalf("StoreVariant() error = %v", err)
} }
@@ -344,7 +346,8 @@ func TestCache_GetVariant_ReturnsContentType(t *testing.T) {
cacheKey := CacheKey(req) cacheKey := CacheKey(req)
outputContent := []byte("output webp data") outputContent := []byte("output webp data")
err := cache.StoreVariant(cacheKey, bytes.NewReader(outputContent), "image/webp") err := cache.StoreVariant(
t.Context(), cacheKey, bytes.NewReader(outputContent), "image/webp")
if err != nil { if err != nil {
t.Fatalf("StoreVariant() error = %v", err) t.Fatalf("StoreVariant() error = %v", err)
} }
@@ -395,7 +398,8 @@ func TestCache_GetVariant(t *testing.T) {
cacheKey := CacheKey(req) cacheKey := CacheKey(req)
outputContent := []byte("the actual output content") outputContent := []byte("the actual output content")
err := cache.StoreVariant(cacheKey, bytes.NewReader(outputContent), "image/webp") err := cache.StoreVariant(
t.Context(), cacheKey, bytes.NewReader(outputContent), "image/webp")
if err != nil { if err != nil {
t.Fatalf("StoreVariant() error = %v", err) t.Fatalf("StoreVariant() error = %v", err)
} }

View File

@@ -114,7 +114,7 @@ func storeEvictionTestVariant(
) { ) {
t.Helper() t.Helper()
err := cache.StoreVariant(key, bytes.NewReader(content), "image/webp") err := cache.StoreVariant(t.Context(), key, bytes.NewReader(content), "image/webp")
if err != nil { if err != nil {
t.Fatalf("StoreVariant(%s) failed: %v", key, err) t.Fatalf("StoreVariant(%s) failed: %v", key, err)
} }
@@ -531,7 +531,7 @@ func assertDisabledCacheWritesAreNoOps(
ctx := t.Context() ctx := t.Context()
err := cache.StoreVariant( err := cache.StoreVariant(
CacheKey(req), bytes.NewReader([]byte("data")), "image/webp", ctx, CacheKey(req), bytes.NewReader([]byte("data")), "image/webp",
) )
if err != nil { if err != nil {
t.Fatalf("StoreVariant on disabled cache must be a no-op, got error: %v", err) t.Fatalf("StoreVariant on disabled cache must be a no-op, got error: %v", err)

View File

@@ -425,7 +425,7 @@ func (s *Service) processAndStore(
// Store variant to cache // Store variant to cache
err = s.cache.StoreVariant( err = s.cache.StoreVariant(
cacheKey, bytes.NewReader(processedData), processResult.ContentType, ctx, cacheKey, bytes.NewReader(processedData), processResult.ContentType,
) )
if err != nil { if err != nil {
s.log.Warn("failed to store variant", "error", err) s.log.Warn("failed to store variant", "error", err)