fix(stats): 今日计数不再被每日缓存冻结,日期分组不依赖库会话时区
自查部署结果时发现两处正确性问题,都是本页上线时引入的: 1. 「今日提问 / 今日回答」原本随整页聚合一整天缓存,页面却写着「实时」, 实际当天第一次访问后数字就冻住到次日。现拆出 TodayCounts 单独取, 60 秒 TTL、跨日按日期失效;命中整页缓存时返回副本,不原地改缓存指针 (那会被并发读踩成数据竞争)。 2. 日/月/时分组用 to_char/EXTRACT 直接作用在 timestamptz 上,结果跟着数据库 会话时区走,而 PG 官方镜像默认 UTC、Go 侧按容器时区(Asia/Shanghai)切今天。 实测同一条 2026-10-24 01:30+08 的提问,UTC 会话下被算成 10-23 17 点 —— 日报表整体偏 8 小时、热力图时段错位,且与「今日」对不上。 现统一经 analyticsLocalize() 加 AT TIME ZONE INTERVAL 换算,偏移取自 time.Time.Zone()(Go 未设 TZ 时给 "Local",PG 不认该名,故不用 IANA 名)。 过滤条件仍是裸列,索引照用。 另外两处顺手修: - PeakDay 用 >= 比较,并列时会漂到最近的同值日期,与 busiestSlot 的取值规则不一致。 - 聚合改用 context.WithoutCancel + 30s 超时:第一个访客在聚合途中关掉页面时, 排在后面等锁的请求不会各自重跑一遍全表 GROUP BY。 测试:新增 TestTodayNumbersNotFrozen(缓存命中后今日数仍更新、整页聚合当天只算一次) 与 TestTodayCacheExpiresAcrossMidnight;analytics 连真库通过。
This commit is contained in:
@@ -69,9 +69,12 @@ func TestSiteAnalytics(t *testing.T) {
|
||||
require.EqualValues(t, 1, got.ActiveBoxes)
|
||||
require.EqualValues(t, 1, got.AnsweringBoxes)
|
||||
|
||||
// 今日(提问是刚才写的,必然落在今天)
|
||||
require.EqualValues(t, 2, got.TodayQuestions)
|
||||
require.EqualValues(t, 1, got.TodayAnswers)
|
||||
// 今日(提问是刚才写的,必然落在今天)—— 单独取,不随整页聚合缓存
|
||||
dayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
todayQ, todayA, err := store.TodayCounts(ctx, dayStart)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 2, todayQ)
|
||||
require.EqualValues(t, 1, todayA)
|
||||
|
||||
// 日/月趋势里能找到今天与本月
|
||||
today := now.Format("2006-01-02")
|
||||
|
||||
Reference in New Issue
Block a user