Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions tsl/test/isolation/expected/cagg_concurrent_register.out
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ step s3_lock_before_register:
BEGIN; LOCK TABLE _timescaledb_catalog.continuous_aggs_jobs_refresh_ranges;

step s1_run_cagg1_refresh:
CALL refresh_continuous_aggregate('cagg_1', '2020-01-01 00:00:00+00', '2020-01-03 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_1', '2020-01-01 00:00:00+00', '2020-01-03 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step s2_run_cagg2_overlap_refresh:
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step s4_enable_before_process_cagg_invalidations:
SELECT debug_waitpoint_enable('before_process_cagg_invalidations_for_refresh_lock');
Expand All @@ -39,8 +39,8 @@ step s5_show_running_jobs:

cagg_name| start_range| end_range|start_ts_utc |end_ts_utc
---------+----------------+----------------+------------------------+------------------------
cagg_1 |1577980800000000|1578009600000000|Thu Jan 02 16:00:00 2020|Fri Jan 03 00:00:00 2020
cagg_2 |1578153600000000|1578182400000000|Sat Jan 04 16:00:00 2020|Sun Jan 05 00:00:00 2020
cagg_1 |1577836800000000|1578009600000000|Wed Jan 01 00:00:00 2020|Fri Jan 03 00:00:00 2020
cagg_2 |1578009600000000|1578182400000000|Fri Jan 03 00:00:00 2020|Sun Jan 05 00:00:00 2020

step s4_release_before_process_cagg_invalidations:
SELECT debug_waitpoint_release('before_process_cagg_invalidations_for_refresh_lock');
Expand All @@ -66,10 +66,10 @@ step s3_lock_before_register:
BEGIN; LOCK TABLE _timescaledb_catalog.continuous_aggs_jobs_refresh_ranges;

step s1_run_cagg2_overlap_refresh:
CALL refresh_continuous_aggregate('cagg_2', '2020-01-01 00:00:00+00', '2020-01-07 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_2', '2020-01-01 00:00:00+00', '2020-01-07 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step s2_run_cagg2_overlap_refresh:
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step s4_enable_before_process_cagg_invalidations:
SELECT debug_waitpoint_enable('before_process_cagg_invalidations_for_refresh_lock');
Expand All @@ -92,15 +92,14 @@ step s5_show_running_jobs:

cagg_name| start_range| end_range|start_ts_utc |end_ts_utc
---------+----------------+----------------+------------------------+------------------------
cagg_2 |1578153600000000|1578182400000000|Sat Jan 04 16:00:00 2020|Sun Jan 05 00:00:00 2020
cagg_2 |1578268800000000|1578355200000000|Mon Jan 06 00:00:00 2020|Tue Jan 07 00:00:00 2020
cagg_2 |1577836800000000|1578355200000000|Wed Jan 01 00:00:00 2020|Tue Jan 07 00:00:00 2020

step s4_release_before_process_cagg_invalidations:
SELECT debug_waitpoint_release('before_process_cagg_invalidations_for_refresh_lock');
<waiting ...>
step s1_run_cagg2_overlap_refresh: <... completed>
ERROR: could not refresh continuous aggregate "cagg_2" due to a concurrent refresh
step s2_run_cagg2_overlap_refresh: <... completed>
ERROR: could not refresh continuous aggregate "cagg_2" due to a concurrent refresh
step s4_release_before_process_cagg_invalidations: <... completed>
debug_waitpoint_release
-----------------------
Expand All @@ -123,7 +122,7 @@ step s1_run_cagg2_nonoverlap_refresh:
CALL refresh_continuous_aggregate('cagg_2', '2020-01-01 00:00:00+00', '2020-01-02 00:00:00+00');
<waiting ...>
step s2_run_cagg2_overlap_refresh:
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step s4_enable_before_process_cagg_invalidations:
SELECT debug_waitpoint_enable('before_process_cagg_invalidations_for_refresh_lock');
Expand All @@ -147,7 +146,7 @@ step s5_show_running_jobs:
cagg_name| start_range| end_range|start_ts_utc |end_ts_utc
---------+----------------+----------------+------------------------+------------------------
cagg_2 |1577836800000000|1577923200000000|Wed Jan 01 00:00:00 2020|Thu Jan 02 00:00:00 2020
cagg_2 |1578153600000000|1578182400000000|Sat Jan 04 16:00:00 2020|Sun Jan 05 00:00:00 2020
cagg_2 |1578009600000000|1578182400000000|Fri Jan 03 00:00:00 2020|Sun Jan 05 00:00:00 2020

step s4_release_before_process_cagg_invalidations:
SELECT debug_waitpoint_release('before_process_cagg_invalidations_for_refresh_lock');
Expand Down
52 changes: 20 additions & 32 deletions tsl/test/isolation/expected/cagg_refresh_cleanup_register.out
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ debug_waitpoint_enable


step R2_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step L1_lock:
BEGIN;
Expand All @@ -20,10 +20,10 @@ debug_waitpoint_release


step R3_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step R4_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-03-15', '2026-03-30');
CALL refresh_continuous_aggregate('cond_daily', '2026-03-15', '2026-03-30', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step check_locks:
SELECT l.mode, l.granted
Expand All @@ -50,7 +50,7 @@ step check_jobs:

user_view_name|start_time |end_time
--------------+----------------------------+----------------------------
cond_daily |Sun Feb 08 16:00:00 2026 PST|Sat Feb 14 16:00:00 2026 PST
cond_daily |Mon Jan 05 16:00:00 2026 PST|Sat Feb 14 16:00:00 2026 PST

step L1_unlock:
COMMIT;
Expand Down Expand Up @@ -89,7 +89,7 @@ debug_waitpoint_enable


step R2_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step L1_lock:
BEGIN;
Expand All @@ -102,10 +102,10 @@ debug_waitpoint_release


step R3_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step R4_overlapping_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-03-01', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-03-01', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step check_locks:
SELECT l.mode, l.granted
Expand All @@ -132,7 +132,7 @@ step check_jobs:

user_view_name|start_time |end_time
--------------+----------------------------+----------------------------
cond_daily |Sun Feb 08 16:00:00 2026 PST|Sat Feb 14 16:00:00 2026 PST
cond_daily |Mon Jan 05 16:00:00 2026 PST|Sat Feb 14 16:00:00 2026 PST

step L1_unlock:
COMMIT;
Expand Down Expand Up @@ -172,7 +172,7 @@ debug_waitpoint_enable


step R3_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step check_jobs:
SELECT ca.user_view_name,
Expand All @@ -185,7 +185,7 @@ step check_jobs:

user_view_name|start_time |end_time
--------------+----------------------------+----------------------------
cond_daily |Sat Mar 07 16:00:00 2026 PST|Sat Mar 14 17:00:00 2026 PDT
cond_daily |Sun Feb 15 16:00:00 2026 PST|Sat Mar 14 17:00:00 2026 PDT

step A1_revoke_perm:
REVOKE SELECT on conditions FROM cagg_user;
Expand Down Expand Up @@ -217,7 +217,7 @@ debug_waitpoint_enable


step R3_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step check_jobs:
SELECT ca.user_view_name,
Expand All @@ -230,7 +230,7 @@ step check_jobs:

user_view_name|start_time |end_time
--------------+----------------------------+----------------------------
cond_daily |Sat Mar 07 16:00:00 2026 PST|Sat Mar 14 17:00:00 2026 PDT
cond_daily |Sun Feb 15 16:00:00 2026 PST|Sat Mar 14 17:00:00 2026 PDT

step A1_revoke_mat_perm:
DO $$
Expand Down Expand Up @@ -273,7 +273,7 @@ debug_waitpoint_enable


step R2_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step check_jobs_metadata_manual:
SELECT ca.user_view_name,
Expand Down Expand Up @@ -352,7 +352,7 @@ debug_waitpoint_enable


step R1_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step check_jobs:
SELECT ca.user_view_name,
Expand All @@ -365,24 +365,11 @@ step check_jobs:

user_view_name|start_time |end_time
--------------+----------------------------+----------------------------
cond_daily |Tue Mar 10 17:00:00 2026 PDT|Sat Mar 14 17:00:00 2026 PDT
cond_daily |Mon Jan 05 16:00:00 2026 PST|Sat Mar 14 17:00:00 2026 PDT

step K1_terminate:
DO $$
DECLARE
target_pid int;
BEGIN
SELECT pid INTO target_pid FROM cancelpid;
PERFORM pg_terminate_backend(target_pid);
LOOP
EXIT WHEN NOT EXISTS (
SELECT 1 FROM pg_stat_activity WHERE pid = target_pid
);
PERFORM pg_sleep(0.05);
END LOOP;
END;
$$;

CALL terminate_r1();
<waiting ...>
step R1_refresh: <... completed>
FATAL: terminating connection due to administrator command
server closed the connection unexpectedly
Expand All @@ -394,16 +381,17 @@ debug_waitpoint_release
-----------------------


step K1_terminate: <... completed>
step L1_lock:
BEGIN;
LOCK TABLE _timescaledb_catalog.continuous_aggs_jobs_refresh_ranges
IN ACCESS EXCLUSIVE MODE;

step R2_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step R3_refresh:
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
<waiting ...>
step L1_unlock:
COMMIT;
Expand Down
6 changes: 3 additions & 3 deletions tsl/test/isolation/specs/cagg_concurrent_register.spec
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ teardown {

session "S1"
step "s1_run_cagg1_refresh" {
CALL refresh_continuous_aggregate('cagg_1', '2020-01-01 00:00:00+00', '2020-01-03 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_1', '2020-01-01 00:00:00+00', '2020-01-03 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
}
step "s1_run_cagg2_overlap_refresh" {
CALL refresh_continuous_aggregate('cagg_2', '2020-01-01 00:00:00+00', '2020-01-07 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_2', '2020-01-01 00:00:00+00', '2020-01-07 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
}
step "s1_run_cagg2_nonoverlap_refresh" {
CALL refresh_continuous_aggregate('cagg_2', '2020-01-01 00:00:00+00', '2020-01-02 00:00:00+00');
Expand All @@ -76,7 +76,7 @@ step "s1_run_cagg2_nonoverlap_refresh" {
session "S2"

step "s2_run_cagg2_overlap_refresh" {
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00');
CALL refresh_continuous_aggregate('cagg_2', '2020-01-03 00:00:00+00', '2020-01-05 00:00:00+00', options => jsonb_build_object('buckets_per_batch', 0));
}

step "s2_insert_new_data_2020" {
Expand Down
41 changes: 20 additions & 21 deletions tsl/test/isolation/specs/cagg_refresh_cleanup_register.spec
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ setup
-- Table used to pass R1's backend PID to the terminator session
CREATE TABLE cancelpid (pid int);

-- Terminate R1's backend. Wrapped in a void-returning procedure (as in
-- cagg_cancel_kill_refresh.spec) so isolationtester's native blocked-step
-- synchronization can be used instead of polling pg_stat_activity.
CREATE OR REPLACE PROCEDURE terminate_r1() AS
$$
BEGIN
PERFORM pg_terminate_backend(pid) FROM cancelpid;
END;
$$ LANGUAGE plpgsql;

CREATE MATERIALIZED VIEW cond_daily
WITH (timescaledb.continuous, timescaledb.materialized_only = true) AS
SELECT time_bucket('1 day', time) AS bucket, avg(value) AS avg_val
Expand Down Expand Up @@ -59,7 +69,7 @@ setup {
INSERT INTO cancelpid SELECT pg_backend_pid();
}
step "R1_refresh" {
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
}

# Session WP: enables / disables waitpoints
Expand All @@ -76,23 +86,12 @@ step "WP_after_register_enable" { SELECT debug_waitpoint_enable('cagg_refresh_a
step "WP_after_register_disable" { SELECT debug_waitpoint_release('cagg_refresh_after_register'); }

# Session K1: terminate R1's backend so its PID becomes dead in the
# registration table, then wait until the process is gone.
# registration table. Relies on isolationtester's native blocked-step
# synchronization (see the "K1_terminate"("R1_refresh") annotation below)
# rather than polling pg_stat_activity for the pid to disappear.
session "K1"
step "K1_terminate" {
DO $$
DECLARE
target_pid int;
BEGIN
SELECT pid INTO target_pid FROM cancelpid;
PERFORM pg_terminate_backend(target_pid);
LOOP
EXIT WHEN NOT EXISTS (
SELECT 1 FROM pg_stat_activity WHERE pid = target_pid
);
PERFORM pg_sleep(0.05);
END LOOP;
END;
$$;
CALL terminate_r1();
}

# Refresh sessions
Expand All @@ -102,7 +101,7 @@ setup {
SET SESSION lock_timeout = '2s';
}
step "R2_refresh" {
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-01-05', '2026-02-15', options => jsonb_build_object('buckets_per_batch', 0));
}

session "R3"
Expand All @@ -111,7 +110,7 @@ setup {
SET SESSION lock_timeout = '2s';
}
step "R3_refresh" {
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-02-15', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
}

session "R4"
Expand All @@ -120,10 +119,10 @@ setup {
SET SESSION lock_timeout = '2s';
}
step "R4_refresh" {
CALL refresh_continuous_aggregate('cond_daily', '2026-03-15', '2026-03-30');
CALL refresh_continuous_aggregate('cond_daily', '2026-03-15', '2026-03-30', options => jsonb_build_object('buckets_per_batch', 0));
}
step "R4_overlapping_refresh" {
CALL refresh_continuous_aggregate('cond_daily', '2026-03-01', '2026-03-15');
CALL refresh_continuous_aggregate('cond_daily', '2026-03-01', '2026-03-15', options => jsonb_build_object('buckets_per_batch', 0));
}

session "A1"
Expand Down Expand Up @@ -241,4 +240,4 @@ permutation "P1_add_policy" "WP_after_register_enable" "P1_run_policy" "check_jo
# Stale registration cleanup by concurrent refreshes.
# Kill a backend during refresh to end up with a pid left behind. Later two concurrent refreshes run, only one removes the stale pid.
# backend R1 is killed, we can no longer use this for later permutations
permutation "WP_before_txn2_commit_enable" "R1_refresh" "check_jobs" "K1_terminate"("check_jobs") "WP_before_txn2_commit_disable" "L1_lock" "R2_refresh"("L1_lock") "R3_refresh"("R2_refresh") "L1_unlock"(R2_refresh, R3_refresh) "check_jobs"
permutation "WP_before_txn2_commit_enable" "R1_refresh" "check_jobs" "K1_terminate"("R1_refresh") "WP_before_txn2_commit_disable" "L1_lock" "R2_refresh"("L1_lock") "R3_refresh"("R2_refresh") "L1_unlock"(R2_refresh, R3_refresh) "check_jobs"
Loading