From 7e608d423045e18816e9f60df4b874f52ebb6525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8E=86=E5=86=B0=E9=83=81-hermes=E7=89=88?= Date: Sat, 9 May 2026 20:10:18 +0800 Subject: [PATCH] fix: ensure analytics date dimension for tracking events --- .../BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md | 8 +++++--- docs/technical/SPACETIMEDB_TABLE_CATALOG.md | 2 +- server-rs/crates/spacetime-module/src/runtime/profile.rs | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/technical/BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md b/docs/technical/BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md index adec3097..14cb7ec2 100644 --- a/docs/technical/BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md +++ b/docs/technical/BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md @@ -27,9 +27,11 @@ 该入口复用既有运行态埋点写入能力: -1. 写入原始事实 `tracking_event`。 -2. 更新聚合投影 `tracking_daily_stat`。 -3. 触发依赖事件进度的个人任务刷新。 +1. 按 `occurred_at_micros` 计算北京时间业务日 `day_key`。 +2. 按同一 `day_key` 幂等补齐 `analytics_date_dimension`,保证周/月/季/年聚合查询有日期 bucket 映射。 +3. 写入原始事实 `tracking_event`。 +4. 更新聚合投影 `tracking_daily_stat`。 +5. 触发依赖事件进度的个人任务刷新。 每日登录 `daily_login` 也必须走该通用 procedure:认证链路仍保留 `record_daily_login_tracking_event_after_auth_success(...)` 作为业务语义 helper,但 helper 内部构造 `TrackingEventDraft` 后调用 `record_tracking_event_after_success(...)`,不再绕到每日登录专用 SpacetimeDB procedure。 diff --git a/docs/technical/SPACETIMEDB_TABLE_CATALOG.md b/docs/technical/SPACETIMEDB_TABLE_CATALOG.md index 667c0a99..c16fd44a 100644 --- a/docs/technical/SPACETIMEDB_TABLE_CATALOG.md +++ b/docs/technical/SPACETIMEDB_TABLE_CATALOG.md @@ -165,7 +165,7 @@ SELECT * FROM profile_wallet_ledger WHERE user_id = '' ORDER BY created - 作用:分析日期维表,每个北京时间业务自然日一行,用于把日桶映射到周、月、季度和年。 - 结构:`date_key PK: i64`, `calendar_date: String`, `weekday: u8`, `iso_week_key: i32`, `week_start_date_key: i64`, `week_end_date_key: i64`, `month_key: i32`, `month_start_date_key: i64`, `month_end_date_key: i64`, `quarter_key: i32`, `quarter_start_date_key: i64`, `quarter_end_date_key: i64`, `year_key: i32`, `year_start_date_key: i64`, `year_end_date_key: i64`, `created_at: Timestamp`, `updated_at: Timestamp`。 - 索引:主键 `date_key`,`iso_week_key`,`month_key`,`quarter_key`,`year_key`。 -- 写入口:`ensure_analytics_date_dimension_for_date({ date_key })` 幂等补单日;`seed_analytics_date_dimensions({ start_date, end_date })` 按 `YYYY-MM-DD` 闭区间幂等批量补种,单次最多 `3660` 天。 +- 写入口:`ensure_analytics_date_dimension_for_date({ date_key })` 幂等补单日;`seed_analytics_date_dimensions({ start_date, end_date })` 按 `YYYY-MM-DD` 闭区间幂等批量补种,单次最多 `3660` 天;通用埋点写入 `record_tracking_event_and_return` 会在写入 `tracking_event` / `tracking_daily_stat` 前按同一 `day_key` 自动幂等补齐当日维表。 - 口径:`date_key` 沿用当前埋点日桶 `floor((occurred_at_micros + 8h) / 1d)`,`calendar_date` 是该北京时间业务日的公历日期。 ```sql diff --git a/server-rs/crates/spacetime-module/src/runtime/profile.rs b/server-rs/crates/spacetime-module/src/runtime/profile.rs index 7ba91942..2aa624ba 100644 --- a/server-rs/crates/spacetime-module/src/runtime/profile.rs +++ b/server-rs/crates/spacetime-module/src/runtime/profile.rs @@ -3048,6 +3048,8 @@ fn record_tracking_event( .map_err(|error| error.to_string())?; let occurred_at = Timestamp::from_micros_since_unix_epoch(validated_input.occurred_at_micros); let day_key = runtime_profile_beijing_day_key(validated_input.occurred_at_micros); + // 中文注释:埋点事实与日期维表使用同一北京时间业务日桶,先幂等补齐维表,避免后续周/月/季/年聚合缺少 bucket 映射。 + ensure_analytics_date_dimension_row(ctx, day_key)?; ctx.db.tracking_event().insert(TrackingEvent { event_id: validated_input.event_id, event_key: validated_input.event_key.clone(),