forked from timescale/timescaledb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcagg_concurrent_policy_register.spec
More file actions
206 lines (181 loc) · 6.32 KB
/
Copy pathcagg_concurrent_policy_register.spec
File metadata and controls
206 lines (181 loc) · 6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# This file and its contents are licensed under the Timescale License.
# Please see the included NOTICE for copyright information and
# LICENSE-TIMESCALE for a copy of the license.
#
#
# Setup:
# hypertable (test_3pol_timestamptz)
# -> L1 CAgg (mat_3pol_m1) 3 adjacent refresh policies
# -> L2 CAgg (mat_2pol_m2) 2 adjacent refresh policies (hierarchical)
#
setup
{
-- create 3 adjacent policies ---
SELECT _timescaledb_functions.stop_background_workers();
CREATE TABLE test_3pol_timestamptz (
time timestamptz NOT NULL,
a INTEGER,
b INTEGER
);
SELECT create_hypertable('test_3pol_timestamptz', 'time', chunk_time_interval => '1 day'::interval);
INSERT INTO test_3pol_timestamptz
SELECT t, 1, (random() * 100)::int
FROM
generate_series('2025-05-20T11:05:00+00', '2025-05-27T12:05:00+00', INTERVAL '1 hour') t;
CREATE MATERIALIZED VIEW mat_3pol_m1
WITH (timescaledb.continuous, timescaledb.materialized_only=true)
AS
SELECT
time_bucket('1 hour', time) AS bucket,
count(a),
sum(b)
FROM test_3pol_timestamptz
GROUP BY 1
WITH NO DATA;
/* Three adjacent policies on mat_3pol_m1 */
CREATE TABLE cagg_policy_jobs (job_id integer, job_name text);
INSERT INTO cagg_policy_jobs
SELECT add_continuous_aggregate_policy('mat_3pol_m1', '7 days'::interval, '3 days'::interval, '12 h'::interval, buckets_per_batch => 0),
'job_7d_3d';
INSERT INTO cagg_policy_jobs
SELECT add_continuous_aggregate_policy('mat_3pol_m1', '3 days'::interval, '1 day'::interval, '12 h'::interval, buckets_per_batch => 0),
'job_3d_1d';
INSERT INTO cagg_policy_jobs
SELECT add_continuous_aggregate_policy('mat_3pol_m1', '1 day'::interval, '1 hour'::interval, '12 h'::interval, buckets_per_batch => 0),
'job_1d_1h';
}
# Materialize L1 so the hierarchical L2 CAgg has source data
setup
{
CALL refresh_continuous_aggregate('mat_3pol_m1', NULL, NULL);
}
# Create the hierarchical L2 CAgg with two adjacent refresh policies of its own
setup
{
CREATE MATERIALIZED VIEW mat_2pol_m2
WITH (timescaledb.continuous, timescaledb.materialized_only=true)
AS
SELECT
time_bucket('1 day', bucket) AS bucket,
sum(count) AS cnt,
sum(sum) AS sumb
FROM mat_3pol_m1
GROUP BY 1
WITH NO DATA;
INSERT INTO cagg_policy_jobs
SELECT add_continuous_aggregate_policy('mat_2pol_m2', NULL, '3 days'::interval, '12 h'::interval, buckets_per_batch => 0),
'l2_job_hist';
INSERT INTO cagg_policy_jobs
SELECT add_continuous_aggregate_policy('mat_2pol_m2', '3 days'::interval, '1 hour'::interval, '12 h'::interval, buckets_per_batch => 0),
'l2_job_recent';
}
teardown {
DROP MATERIALIZED VIEW IF EXISTS mat_2pol_m2 CASCADE;
DROP MATERIALIZED VIEW IF EXISTS mat_3pol_m1 CASCADE;
DROP TABLE IF EXISTS test_3pol_timestamptz CASCADE;
DROP TABLE IF EXISTS cagg_policy_jobs;
}
session "S1"
setup
{
SET timescaledb.current_timestamp_mock TO '2025-05-27 12:30:00+00';
SET client_min_messages TO error;
}
step "s1_select" {
select min(time) at time zone 'UTC' , max(time) at time zone 'UTC'
FROM test_3pol_timestamptz;
}
step "s1_run_pol7d_3d_refresh" {
DO $$
DECLARE
jid integer;
BEGIN
SELECT job_id INTO jid FROM cagg_policy_jobs WHERE job_name = 'job_7d_3d';
CALL run_job(jid);
END;
$$;
}
step "s1_run_l2_hist" {
DO $$
DECLARE
jid integer;
BEGIN
SELECT job_id INTO jid FROM cagg_policy_jobs WHERE job_name = 'l2_job_hist';
CALL run_job(jid);
END;
$$;
}
session "S12"
setup
{
SET timescaledb.current_timestamp_mock TO '2025-05-27 12:30:00+00';
SET client_min_messages TO error;
}
step "s12_run_pol3d_1d_refresh" {
DO $$
DECLARE
jid integer;
BEGIN
SELECT job_id INTO jid FROM cagg_policy_jobs WHERE job_name = 'job_3d_1d';
CALL run_job(jid);
END;
$$;
}
step "s12_run_l2_recent" {
DO $$
DECLARE
jid integer;
BEGIN
SELECT job_id INTO jid FROM cagg_policy_jobs WHERE job_name = 'l2_job_recent';
CALL run_job(jid);
END;
$$;
}
session "S13"
setup
{
SET timescaledb.current_timestamp_mock TO '2025-05-27 12:30:00+00';
SET client_min_messages TO error;
}
step "s13_run_pol1d_refresh" {
DO $$
DECLARE
jid integer;
BEGIN
SELECT job_id INTO jid FROM cagg_policy_jobs WHERE job_name = 'job_1d_1h';
CALL run_job(jid);
END;
$$;
}
session "S3"
step "s3_lock_before_register" {
-- lock jobs_refresh_ranges table to serialize registration
BEGIN; LOCK TABLE _timescaledb_catalog.continuous_aggs_jobs_refresh_ranges;
}
step "s3_release_after_register" {
-- release lock on jobs_refresh_ranges table
ROLLBACK;
}
session "S4"
step "s4_enable_before_process_cagg_invalidations" {
SELECT debug_waitpoint_enable('before_process_cagg_invalidations_for_refresh_lock');
}
step "s4_release_before_process_cagg_invalidations" {
SELECT debug_waitpoint_release('before_process_cagg_invalidations_for_refresh_lock');
}
session "S5"
step "s5_show_running_jobs" {
SELECT ca.user_view_name AS cagg_name, r.start_range, r.end_range,
to_timestamp(r.start_range / 1000000) AT TIME ZONE 'UTC' AS start_ts_utc,
to_timestamp(r.end_range / 1000000) AT TIME ZONE 'UTC' AS end_ts_utc
FROM _timescaledb_catalog.continuous_aggs_jobs_refresh_ranges r
JOIN _timescaledb_catalog.continuous_agg ca ON r.materialization_id = ca.mat_hypertable_id
ORDER BY ca.user_view_name, start_range;
}
## TEST: when 3 concurrent refresh policies execute, they serialize on registration, then execute succesfully
## since these are adjacent policies 2 concurrent refresh processes, the extend last bucket behavior will apply
## observe the ranges recorded for each policy run
permutation "s1_select" "s3_lock_before_register" "s1_run_pol7d_3d_refresh" "s12_run_pol3d_1d_refresh"("s1_run_pol7d_3d_refresh") "s13_run_pol1d_refresh"("s12_run_pol3d_1d_refresh") "s4_enable_before_process_cagg_invalidations" "s3_release_after_register" "s5_show_running_jobs" "s4_release_before_process_cagg_invalidations"
## TEST: two concurrent refresh policies on the hierarchical L2 CAgg serialize on registration,
## then both execute succesfully.
permutation "s3_lock_before_register" "s1_run_l2_hist" "s12_run_l2_recent"("s1_run_l2_hist") "s4_enable_before_process_cagg_invalidations" "s3_release_after_register" "s5_show_running_jobs" "s4_release_before_process_cagg_invalidations"