feat: add jikan cache stats query
This commit is contained in:
@@ -86,6 +86,33 @@ func TestGetWithCacheAllowsEmptySearchResults(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetJikanCacheStatsCountsRowsAndExpiry(t *testing.T) {
|
||||||
|
sqlDB := newTestCacheDB(t)
|
||||||
|
defer func() {
|
||||||
|
if err := sqlDB.Close(); err != nil {
|
||||||
|
t.Errorf("close sqlite: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
oldest := time.Date(2026, 6, 20, 12, 0, 0, 0, time.UTC)
|
||||||
|
insertCachedResponse(t, sqlDB, "expired", TopAnimeResponse{Data: []Anime{{MalID: 1}}}, oldest)
|
||||||
|
insertCachedResponse(t, sqlDB, "fresh", TopAnimeResponse{Data: []Anime{{MalID: 2}}}, time.Now().Add(time.Hour))
|
||||||
|
|
||||||
|
stats, err := db.New(sqlDB).GetJikanCacheStats(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetJikanCacheStats: %v", err)
|
||||||
|
}
|
||||||
|
if stats.TotalRows != 2 {
|
||||||
|
t.Fatalf("TotalRows = %d, want 2", stats.TotalRows)
|
||||||
|
}
|
||||||
|
if stats.ExpiredRows != 1 {
|
||||||
|
t.Fatalf("ExpiredRows = %d, want 1", stats.ExpiredRows)
|
||||||
|
}
|
||||||
|
if stats.OldestExpiresAtSeconds != oldest.Unix() {
|
||||||
|
t.Fatalf("OldestExpiresAtSeconds = %d, want %d", stats.OldestExpiresAtSeconds, oldest.Unix())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newTestCacheDB(t *testing.T) *sql.DB {
|
func newTestCacheDB(t *testing.T) *sql.DB {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type Querier interface {
|
|||||||
GetEpisodeAvailabilityCache(ctx context.Context, animeID int64) (EpisodeAvailabilityCache, error)
|
GetEpisodeAvailabilityCache(ctx context.Context, animeID int64) (EpisodeAvailabilityCache, error)
|
||||||
GetEpisodeProviderMapping(ctx context.Context, arg GetEpisodeProviderMappingParams) (EpisodeProviderMapping, error)
|
GetEpisodeProviderMapping(ctx context.Context, arg GetEpisodeProviderMappingParams) (EpisodeProviderMapping, error)
|
||||||
GetJikanCache(ctx context.Context, key string) (string, error)
|
GetJikanCache(ctx context.Context, key string) (string, error)
|
||||||
|
GetJikanCacheStats(ctx context.Context) (GetJikanCacheStatsRow, error)
|
||||||
GetJikanCacheStale(ctx context.Context, key string) (string, error)
|
GetJikanCacheStale(ctx context.Context, key string) (string, error)
|
||||||
GetSession(ctx context.Context, id string) (Session, error)
|
GetSession(ctx context.Context, id string) (Session, error)
|
||||||
GetTrackedAiringAnimeIDsDueForEpisodeRefresh(ctx context.Context, limit int64) ([]int64, error)
|
GetTrackedAiringAnimeIDsDueForEpisodeRefresh(ctx context.Context, limit int64) ([]int64, error)
|
||||||
|
|||||||
@@ -235,6 +235,13 @@ WHERE key = ? AND datetime(expires_at) > CURRENT_TIMESTAMP LIMIT 1;
|
|||||||
SELECT data FROM jikan_cache
|
SELECT data FROM jikan_cache
|
||||||
WHERE key = ? LIMIT 1;
|
WHERE key = ? LIMIT 1;
|
||||||
|
|
||||||
|
-- name: GetJikanCacheStats :one
|
||||||
|
SELECT
|
||||||
|
COUNT(*) AS total_rows,
|
||||||
|
COUNT(*) FILTER (WHERE datetime(expires_at) <= CURRENT_TIMESTAMP) AS expired_rows,
|
||||||
|
COALESCE(unixepoch(MIN(expires_at)), 0) AS oldest_expires_at_seconds
|
||||||
|
FROM jikan_cache;
|
||||||
|
|
||||||
-- name: SetJikanCache :exec
|
-- name: SetJikanCache :exec
|
||||||
INSERT INTO jikan_cache (key, data, expires_at)
|
INSERT INTO jikan_cache (key, data, expires_at)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
|
|||||||
@@ -565,6 +565,27 @@ func (q *Queries) GetJikanCache(ctx context.Context, key string) (string, error)
|
|||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getJikanCacheStats = `-- name: GetJikanCacheStats :one
|
||||||
|
SELECT
|
||||||
|
COUNT(*) AS total_rows,
|
||||||
|
COUNT(*) FILTER (WHERE datetime(expires_at) <= CURRENT_TIMESTAMP) AS expired_rows,
|
||||||
|
COALESCE(unixepoch(MIN(expires_at)), 0) AS oldest_expires_at_seconds
|
||||||
|
FROM jikan_cache
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetJikanCacheStatsRow struct {
|
||||||
|
TotalRows int64 `json:"total_rows"`
|
||||||
|
ExpiredRows int64 `json:"expired_rows"`
|
||||||
|
OldestExpiresAtSeconds int64 `json:"oldest_expires_at_seconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetJikanCacheStats(ctx context.Context) (GetJikanCacheStatsRow, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, getJikanCacheStats)
|
||||||
|
var i GetJikanCacheStatsRow
|
||||||
|
err := row.Scan(&i.TotalRows, &i.ExpiredRows, &i.OldestExpiresAtSeconds)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
const getJikanCacheStale = `-- name: GetJikanCacheStale :one
|
const getJikanCacheStale = `-- name: GetJikanCacheStale :one
|
||||||
SELECT data FROM jikan_cache
|
SELECT data FROM jikan_cache
|
||||||
WHERE key = ? LIMIT 1
|
WHERE key = ? LIMIT 1
|
||||||
|
|||||||
Reference in New Issue
Block a user