Some checks failed
CI / verify (push) Has been cancelled
- lock profile task tracking scope to user - add analytics date dimension module support and tests - regenerate SpacetimeDB Rust bindings with private APIs
127 lines
4.4 KiB
Rust
127 lines
4.4 KiB
Rust
use crate::*;
|
||
|
||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||
pub struct AnalyticsDateDimensionEnsureInput {
|
||
pub date_key: i64,
|
||
}
|
||
|
||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||
pub struct AnalyticsDateDimensionSeedInput {
|
||
pub start_date: String,
|
||
pub end_date: String,
|
||
}
|
||
|
||
#[spacetimedb::table(
|
||
accessor = analytics_date_dimension,
|
||
index(accessor = by_analytics_date_dimension_iso_week, btree(columns = [iso_week_key])),
|
||
index(accessor = by_analytics_date_dimension_month, btree(columns = [month_key])),
|
||
index(accessor = by_analytics_date_dimension_quarter, btree(columns = [quarter_key])),
|
||
index(accessor = by_analytics_date_dimension_year, btree(columns = [year_key]))
|
||
)]
|
||
pub struct AnalyticsDateDimension {
|
||
#[primary_key]
|
||
pub(crate) date_key: i64,
|
||
// 中文注释:北京时间业务日对应的公历日期,格式 YYYY-MM-DD。
|
||
pub(crate) calendar_date: String,
|
||
// 中文注释:ISO weekday,周一=1,周日=7,方便统计层不重复计算。
|
||
pub(crate) weekday: u8,
|
||
// 中文注释:ISO week 编码为 YYYYWW,跨年周按 ISO 年归属。
|
||
pub(crate) iso_week_key: i32,
|
||
pub(crate) week_start_date_key: i64,
|
||
pub(crate) week_end_date_key: i64,
|
||
pub(crate) month_key: i32,
|
||
pub(crate) month_start_date_key: i64,
|
||
pub(crate) month_end_date_key: i64,
|
||
pub(crate) quarter_key: i32,
|
||
pub(crate) quarter_start_date_key: i64,
|
||
pub(crate) quarter_end_date_key: i64,
|
||
pub(crate) year_key: i32,
|
||
pub(crate) year_start_date_key: i64,
|
||
pub(crate) year_end_date_key: i64,
|
||
pub(crate) created_at: Timestamp,
|
||
pub(crate) updated_at: Timestamp,
|
||
}
|
||
|
||
#[spacetimedb::reducer]
|
||
pub fn ensure_analytics_date_dimension_for_date(
|
||
ctx: &ReducerContext,
|
||
input: AnalyticsDateDimensionEnsureInput,
|
||
) -> Result<(), String> {
|
||
ensure_analytics_date_dimension_row(ctx, input.date_key)?;
|
||
Ok(())
|
||
}
|
||
|
||
#[spacetimedb::reducer]
|
||
pub fn seed_analytics_date_dimensions(
|
||
ctx: &ReducerContext,
|
||
input: AnalyticsDateDimensionSeedInput,
|
||
) -> Result<(), String> {
|
||
let start_date_key = parse_analytics_calendar_date_key(&input.start_date)
|
||
.map_err(|error| format!("invalid start_date: {error}"))?;
|
||
let end_date_key = parse_analytics_calendar_date_key(&input.end_date)
|
||
.map_err(|error| format!("invalid end_date: {error}"))?;
|
||
if start_date_key > end_date_key {
|
||
return Err("start_date must be <= end_date".to_string());
|
||
}
|
||
let seed_days = end_date_key - start_date_key + 1;
|
||
if seed_days > ANALYTICS_DATE_DIMENSION_MAX_SEED_DAYS {
|
||
return Err(format!(
|
||
"date range too large: max {} days",
|
||
ANALYTICS_DATE_DIMENSION_MAX_SEED_DAYS
|
||
));
|
||
}
|
||
|
||
for date_key in start_date_key..=end_date_key {
|
||
ensure_analytics_date_dimension_row(ctx, date_key)?;
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
pub(crate) fn ensure_analytics_date_dimension_row(
|
||
ctx: &ReducerContext,
|
||
date_key: i64,
|
||
) -> Result<(), String> {
|
||
validate_analytics_date_dimension_date_key(date_key)
|
||
.map_err(|error| format!("invalid date_key: {error}"))?;
|
||
if ctx
|
||
.db
|
||
.analytics_date_dimension()
|
||
.date_key()
|
||
.find(&date_key)
|
||
.is_some()
|
||
{
|
||
return Ok(());
|
||
}
|
||
|
||
let snapshot = build_analytics_date_dimension_from_date_key(date_key);
|
||
ctx.db
|
||
.analytics_date_dimension()
|
||
.insert(build_analytics_date_dimension_row(snapshot, ctx.timestamp));
|
||
Ok(())
|
||
}
|
||
|
||
fn build_analytics_date_dimension_row(
|
||
snapshot: AnalyticsDateDimensionSnapshot,
|
||
now: Timestamp,
|
||
) -> AnalyticsDateDimension {
|
||
AnalyticsDateDimension {
|
||
date_key: snapshot.date_key,
|
||
calendar_date: snapshot.calendar_date,
|
||
weekday: snapshot.weekday,
|
||
iso_week_key: snapshot.iso_week_key,
|
||
week_start_date_key: snapshot.week_start_date_key,
|
||
week_end_date_key: snapshot.week_end_date_key,
|
||
month_key: snapshot.month_key,
|
||
month_start_date_key: snapshot.month_start_date_key,
|
||
month_end_date_key: snapshot.month_end_date_key,
|
||
quarter_key: snapshot.quarter_key,
|
||
quarter_start_date_key: snapshot.quarter_start_date_key,
|
||
quarter_end_date_key: snapshot.quarter_end_date_key,
|
||
year_key: snapshot.year_key,
|
||
year_start_date_key: snapshot.year_start_date_key,
|
||
year_end_date_key: snapshot.year_end_date_key,
|
||
created_at: now,
|
||
updated_at: now,
|
||
}
|
||
}
|