Skip to content

Commit 974588c

Browse files
committed
Thread context.Context through MonthlySamplesCache
Pass context from HTTP handlers through to the cache's database query, allowing cache reloads to be cancelled on request timeout or shutdown.
1 parent c5df1c1 commit 974588c

4 files changed

Lines changed: 18 additions & 16 deletions

File tree

internal/database/cache.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package database
22

33
import (
4+
"context"
45
"database/sql"
56
"fmt"
67
"sync"
@@ -26,8 +27,8 @@ func NewMonthlySamplesCache(db *sql.DB, query string) *MonthlySamplesCache {
2627
return &MonthlySamplesCache{db: db, query: query}
2728
}
2829

29-
func (c *MonthlySamplesCache) Get(startMonth, endMonth int) (map[int]int, error) {
30-
all, err := c.load()
30+
func (c *MonthlySamplesCache) Get(ctx context.Context, startMonth, endMonth int) (map[int]int, error) {
31+
all, err := c.load(ctx)
3132
if err != nil {
3233
return nil, err
3334
}
@@ -42,7 +43,7 @@ func (c *MonthlySamplesCache) Get(startMonth, endMonth int) (map[int]int, error)
4243
return result, nil
4344
}
4445

45-
func (c *MonthlySamplesCache) load() (map[int]int, error) {
46+
func (c *MonthlySamplesCache) load(ctx context.Context) (map[int]int, error) {
4647
c.mu.RLock()
4748
if c.cache != nil && time.Now().Before(c.expiry) {
4849
cache := c.cache
@@ -59,7 +60,7 @@ func (c *MonthlySamplesCache) load() (map[int]int, error) {
5960
return c.cache, nil
6061
}
6162

62-
rows, err := c.db.Query(c.query)
63+
rows, err := c.db.QueryContext(ctx, c.query)
6364
if err != nil {
6465
return nil, fmt.Errorf("query monthly samples: %w", err)
6566
}

internal/database/cache_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package database
22

33
import (
4+
"context"
45
"database/sql"
56
"testing"
67
"time"
@@ -21,7 +22,7 @@ func TestMonthlySamplesCache(t *testing.T) {
2122
cache := NewMonthlySamplesCache(db, "SELECT month, count FROM test_samples")
2223

2324
// First load
24-
res, err := cache.Get(202501, 202502)
25+
res, err := cache.Get(context.Background(), 202501, 202502)
2526
if err != nil {
2627
t.Fatalf("Get error: %v", err)
2728
}
@@ -34,7 +35,7 @@ func TestMonthlySamplesCache(t *testing.T) {
3435

3536
// Update DB, but cache should still be valid
3637
_, _ = db.Exec(`UPDATE test_samples SET count = 300 WHERE month = 202501`)
37-
res, _ = cache.Get(202501, 202502)
38+
res, _ = cache.Get(context.Background(), 202501, 202502)
3839
if res[202501] != 100 {
3940
t.Errorf("expected cached value 100, got %d", res[202501])
4041
}
@@ -44,7 +45,7 @@ func TestMonthlySamplesCache(t *testing.T) {
4445
cache.expiry = time.Now().Add(-1 * time.Hour)
4546
cache.mu.Unlock()
4647

47-
res, _ = cache.Get(202501, 202502)
48+
res, _ = cache.Get(context.Background(), 202501, 202502)
4849
if res[202501] != 300 {
4950
t.Errorf("expected new value 300 after expiry, got %d", res[202501])
5051
}

internal/packages/repository.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,6 @@ func (r *SQLiteRepository) getMaxCount(ctx context.Context, startMonth, endMonth
258258
return total, nil
259259
}
260260

261-
func (r *SQLiteRepository) getMonthlyMaxCounts(_ context.Context, startMonth, endMonth int) (map[int]int, error) {
262-
return r.monthlyMaxCache.Get(startMonth, endMonth)
261+
func (r *SQLiteRepository) getMonthlyMaxCounts(ctx context.Context, startMonth, endMonth int) (map[int]int, error) {
262+
return r.monthlyMaxCache.Get(ctx, startMonth, endMonth)
263263
}

internal/popularity/repository.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (r *Repository[T, L]) FindByIdentifier(ctx context.Context, identifier stri
6969
return nil, fmt.Errorf("query %s count: %w", r.cfg.Table, err)
7070
}
7171

72-
samples, err := r.getSamples(startMonth, endMonth)
72+
samples, err := r.getSamples(ctx, startMonth, endMonth)
7373
if err != nil {
7474
return nil, fmt.Errorf("get samples: %w", err)
7575
}
@@ -80,7 +80,7 @@ func (r *Repository[T, L]) FindByIdentifier(ctx context.Context, identifier stri
8080
}
8181

8282
func (r *Repository[T, L]) FindAll(ctx context.Context, query string, startMonth, endMonth, limit, offset int) (*L, error) {
83-
samples, err := r.getSamples(startMonth, endMonth)
83+
samples, err := r.getSamples(ctx, startMonth, endMonth)
8484
if err != nil {
8585
return nil, fmt.Errorf("get samples: %w", err)
8686
}
@@ -166,7 +166,7 @@ func (r *Repository[T, L]) FindSeries(ctx context.Context, identifier string, st
166166
return nil, fmt.Errorf("count series: %w", err)
167167
}
168168

169-
samplesMap, err := r.getMonthlySamples(startMonth, endMonth)
169+
samplesMap, err := r.getMonthlySamples(ctx, startMonth, endMonth)
170170
if err != nil {
171171
return nil, fmt.Errorf("get monthly samples: %w", err)
172172
}
@@ -214,8 +214,8 @@ func (r *Repository[T, L]) queryPattern(query string) string {
214214
return query + "%"
215215
}
216216

217-
func (r *Repository[T, L]) getSamples(startMonth, endMonth int) (int, error) {
218-
monthlySamples, err := r.getMonthlySamples(startMonth, endMonth)
217+
func (r *Repository[T, L]) getSamples(ctx context.Context, startMonth, endMonth int) (int, error) {
218+
monthlySamples, err := r.getMonthlySamples(ctx, startMonth, endMonth)
219219
if err != nil {
220220
return 0, err
221221
}
@@ -228,8 +228,8 @@ func (r *Repository[T, L]) getSamples(startMonth, endMonth int) (int, error) {
228228
return total, nil
229229
}
230230

231-
func (r *Repository[T, L]) getMonthlySamples(startMonth, endMonth int) (map[int]int, error) {
232-
return r.samplesCache.Get(startMonth, endMonth)
231+
func (r *Repository[T, L]) getMonthlySamples(ctx context.Context, startMonth, endMonth int) (map[int]int, error) {
232+
return r.samplesCache.Get(ctx, startMonth, endMonth)
233233
}
234234

235235
// CalculatePopularity returns a percentage rounded to 2 decimal places, capped at 100.

0 commit comments

Comments
 (0)