Skip to content

Commit a0a341b

Browse files
committed
feat: Change Analytics to be day-based only, compute everything else on the fly (note: analytics now are not compatible yet) + add postgres functions to compute the other data
1 parent 069efff commit a0a341b

2 files changed

Lines changed: 92 additions & 25 deletions

File tree

backend/migrations/0002_analytics.sql

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
create table if not exists user_stats_aggregate (
1+
create table if not exists user_stats_aggregate_daily (
22
user_id int not null,
3-
window_type text not null check (window_type in (
4-
'daily', 'weekly', 'monthly', 'yearly'
5-
)),
63
window_start timestamptz not null,
74
window_end timestamptz not null,
85
lang_durations jsonb default '{}'::jsonb,
@@ -12,33 +9,23 @@ create table if not exists user_stats_aggregate (
129
activity_durations jsonb default '{}'::jsonb,
1310
created_at timestamptz default now(),
1411
updated_at timestamptz default now(),
15-
primary key (user_id, window_type, window_start)
12+
primary key (user_id, window_start)
1613
);
1714

18-
create index if not exists idx_user_stats_time_range on user_stats_aggregate(user_id, window_type, window_start desc);
19-
create index if not exists idx_user_stats_updated on user_stats_aggregate(updated_at) where window_type like 'rolling%';
20-
21-
create table if not exists user_stats_rolling (
22-
user_id int not null,
23-
window_type text not null check (window_type in (
24-
'rolling_24h', 'rolling_7d', 'rolling_30d', 'rolling_365d'
25-
)),
15+
create table if not exists user_stats_rolling_day (
16+
user_id int primary key,
2617
lang_durations jsonb default '{}'::jsonb,
2718
machine_durations jsonb default '{}'::jsonb,
2819
editor_durations jsonb default '{}'::jsonb,
2920
project_durations jsonb default '{}'::jsonb,
3021
activity_durations jsonb default '{}'::jsonb,
3122
created_at timestamptz default now(),
32-
updated_at timestamptz default now(),
33-
primary key (user_id, window_type)
23+
updated_at timestamptz default now()
3424
);
3525

36-
create table if not exists user_project_stats_aggregate (
26+
create table if not exists user_project_stats_aggregate_daily (
3727
user_id integer,
3828
project_path varchar(500) not null,
39-
window_type text not null check (window_type in (
40-
'daily', 'weekly', 'monthly', 'yearly'
41-
)),
4229
window_start timestamp not null,
4330
window_end timestamp not null,
4431
lang_durations jsonb,
@@ -47,22 +34,19 @@ create table if not exists user_project_stats_aggregate (
4734
activity_durations jsonb,
4835
files_durations jsonb,
4936
updated_at timestamptz default now(),
50-
unique (user_id, project_path, window_type, window_start)
37+
unique (user_id, project_path, window_start)
5138
);
5239

53-
create table if not exists user_project_stats_rolling (
40+
create table if not exists user_project_stats_rolling_day (
5441
user_id integer,
5542
project_path varchar(500) not null,
56-
window_type text not null check (window_type in (
57-
'rolling_24h', 'rolling_7d', 'rolling_30d', 'rolling_365d'
58-
)),
5943
lang_durations jsonb,
6044
machine_durations jsonb,
6145
editor_durations jsonb,
6246
activity_durations jsonb,
6347
files_durations jsonb,
6448
updated_at timestamptz default now(),
65-
unique (user_id, project_path, window_type)
49+
unique (user_id, project_path)
6650
);
6751

6852
create table if not exists user_project_session (

backend/migrations/0003_views.sql

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
create or replace function jsonb_sum_aggregate(rows jsonb[])
2+
returns jsonb language plpgsql immutable as $$
3+
declare
4+
result jsonb := '{}';
5+
r jsonb;
6+
k text;
7+
v int;
8+
begin
9+
if rows is null then
10+
return result;
11+
end if;
12+
foreach r in array rows loop
13+
for k, v in select key, value::int from jsonb_each(r) loop
14+
if result ? k then
15+
result := jsonb_set(result, array[k], ((result ->> k)::int + v)::text::jsonb);
16+
else
17+
result := jsonb_set(result, array[k], v::text::jsonb);
18+
end if;
19+
end loop;
20+
end loop;
21+
return result;
22+
end;
23+
$$;
24+
25+
create or replace function user_analytics_aggregate_period(
26+
p_start timestamptz,
27+
p_interval interval
28+
)
29+
returns table (
30+
user_id int,
31+
window_start timestamptz,
32+
window_end timestamptz,
33+
lang_durations jsonb,
34+
machine_durations jsonb,
35+
editor_durations jsonb,
36+
project_durations jsonb,
37+
activity_durations jsonb
38+
) language sql as $$
39+
select
40+
d.user_id,
41+
min(d.window_start) as window_start,
42+
max(d.window_end) as window_end,
43+
jsonb_sum_aggregate(array_agg(d.lang_durations)) as lang_durations,
44+
jsonb_sum_aggregate(array_agg(d.machine_durations)) as machine_durations,
45+
jsonb_sum_aggregate(array_agg(d.editor_durations)) as editor_durations,
46+
jsonb_sum_aggregate(array_agg(d.project_durations)) as project_durations,
47+
jsonb_sum_aggregate(array_agg(d.activity_durations)) as activity_durations
48+
from user_stats_aggregate_daily d
49+
where d.window_start >= p_start
50+
and d.window_start < p_start + p_interval
51+
group by d.user_id;
52+
$$;
53+
54+
create or replace function user_project_analytics_aggregate_period(
55+
p_start timestamptz,
56+
p_interval interval
57+
)
58+
returns table (
59+
user_id int,
60+
project_path varchar,
61+
window_start timestamptz,
62+
window_end timestamptz,
63+
lang_durations jsonb,
64+
machine_durations jsonb,
65+
editor_durations jsonb,
66+
activity_durations jsonb,
67+
files_durations jsonb
68+
) language sql as $$
69+
select
70+
d.user_id,
71+
d.project_path,
72+
min(d.window_start) as window_start,
73+
max(d.window_end) as window_end,
74+
jsonb_sum_aggregate(array_agg(d.lang_durations)) as lang_durations,
75+
jsonb_sum_aggregate(array_agg(d.machine_durations)) as machine_durations,
76+
jsonb_sum_aggregate(array_agg(d.editor_durations)) as editor_durations,
77+
jsonb_sum_aggregate(array_agg(d.activity_durations)) as activity_durations,
78+
jsonb_sum_aggregate(array_agg(d.files_durations)) as files_durations
79+
from user_project_stats_aggregate_daily d
80+
where d.window_start >= p_start
81+
and d.window_start < p_start + p_interval
82+
group by d.user_id, d.project_path;
83+
$$;

0 commit comments

Comments
 (0)