Add isolation test for errors during logical slot creation.
authorAndres Freund <[email protected]>
Tue, 15 Feb 2022 05:52:55 +0000 (21:52 -0800)
committerAndres Freund <[email protected]>
Tue, 15 Feb 2022 05:53:36 +0000 (21:53 -0800)
I didn't include this test in 2f6501fa3c5, because I was not sure the error
messages for the terminated connection is stable across platforms. But it
sounds like it is, and if not, we'd want to do something about the instability
anyway...

Discussion: https://postgr.es/m/CAD21AoDAeEpAbZEyYJsPZJUmSPaRicVSBObaL7sPaofnKz+9zg@mail.gmail.com

contrib/test_decoding/Makefile
contrib/test_decoding/expected/slot_creation_error.out [new file with mode: 0644]
contrib/test_decoding/specs/slot_creation_error.spec [new file with mode: 0644]

index 56ddc3abaebdd6eea3b800e8f4582d2248b6caaa..36929dd97d3894268dce7a8dd1b03274110cb8ed 100644 (file)
@@ -9,7 +9,7 @@ REGRESS = ddl xact rewrite toast permissions decoding_in_xact \
    sequence
 ISOLATION = mxact delayed_startup ondisk_startup concurrent_ddl_dml \
    oldest_xmin snapshot_transfer subxact_without_top concurrent_stream \
-   twophase_snapshot
+   twophase_snapshot slot_creation_error
 
 REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf
 ISOLATION_OPTS = --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf
diff --git a/contrib/test_decoding/expected/slot_creation_error.out b/contrib/test_decoding/expected/slot_creation_error.out
new file mode 100644 (file)
index 0000000..321648c
--- /dev/null
@@ -0,0 +1,113 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1_b s1_xid s2_init s1_view_slot s1_cancel_s2 s1_view_slot s1_c
+step s1_b: BEGIN;
+step s1_xid: SELECT 'xid' FROM txid_current();
+?column?
+--------
+xid     
+(1 row)
+
+step s2_init: 
+    SELECT 'init' FROM pg_create_logical_replication_slot('slot_creation_error', 'test_decoding');
+ <waiting ...>
+step s1_view_slot: 
+    SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
+
+slot_name          |slot_type|active
+-------------------+---------+------
+slot_creation_error|logical  |t     
+(1 row)
+
+step s1_cancel_s2: 
+    SELECT pg_cancel_backend(pid)
+    FROM pg_stat_activity
+    WHERE application_name = 'isolation/slot_creation_error/s2';
+
+pg_cancel_backend
+-----------------
+t                
+(1 row)
+
+step s2_init: <... completed>
+ERROR:  canceling statement due to user request
+step s1_view_slot: 
+    SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
+
+slot_name|slot_type|active
+---------+---------+------
+(0 rows)
+
+step s1_c: COMMIT;
+
+starting permutation: s1_b s1_xid s2_init s1_c s1_view_slot s1_drop_slot
+step s1_b: BEGIN;
+step s1_xid: SELECT 'xid' FROM txid_current();
+?column?
+--------
+xid     
+(1 row)
+
+step s2_init: 
+    SELECT 'init' FROM pg_create_logical_replication_slot('slot_creation_error', 'test_decoding');
+ <waiting ...>
+step s1_c: COMMIT;
+step s2_init: <... completed>
+?column?
+--------
+init    
+(1 row)
+
+step s1_view_slot: 
+    SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
+
+slot_name          |slot_type|active
+-------------------+---------+------
+slot_creation_error|logical  |f     
+(1 row)
+
+step s1_drop_slot: 
+    SELECT pg_drop_replication_slot('slot_creation_error');
+
+pg_drop_replication_slot
+------------------------
+                        
+(1 row)
+
+
+starting permutation: s1_b s1_xid s2_init s1_terminate_s2 s1_c s1_view_slot
+step s1_b: BEGIN;
+step s1_xid: SELECT 'xid' FROM txid_current();
+?column?
+--------
+xid     
+(1 row)
+
+step s2_init: 
+    SELECT 'init' FROM pg_create_logical_replication_slot('slot_creation_error', 'test_decoding');
+ <waiting ...>
+step s1_terminate_s2: 
+    SELECT pg_terminate_backend(pid)
+    FROM pg_stat_activity
+    WHERE application_name = 'isolation/slot_creation_error/s2';
+
+pg_terminate_backend
+--------------------
+t                   
+(1 row)
+
+step s2_init: <... completed>
+FATAL:  terminating connection due to administrator command
+FATAL:  terminating connection due to administrator command
+server closed the connection unexpectedly
+   This probably means the server terminated abnormally
+   before or while processing the request.
+
+step s1_c: COMMIT;
+step s1_view_slot: 
+    SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
+
+slot_name|slot_type|active
+---------+---------+------
+(0 rows)
+
diff --git a/contrib/test_decoding/specs/slot_creation_error.spec b/contrib/test_decoding/specs/slot_creation_error.spec
new file mode 100644 (file)
index 0000000..6816696
--- /dev/null
@@ -0,0 +1,41 @@
+# Test that erroring out during logical slot creation is handled properly
+
+session "s1"
+setup { SET synchronous_commit=on; }
+
+step s1_b { BEGIN; }
+step s1_xid { SELECT 'xid' FROM txid_current(); }
+step s1_c { COMMIT; }
+step s1_cancel_s2 {
+    SELECT pg_cancel_backend(pid)
+    FROM pg_stat_activity
+    WHERE application_name = 'isolation/slot_creation_error/s2';
+}
+
+step s1_terminate_s2 {
+    SELECT pg_terminate_backend(pid)
+    FROM pg_stat_activity
+    WHERE application_name = 'isolation/slot_creation_error/s2';
+}
+
+step s1_view_slot {
+    SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
+}
+
+step s1_drop_slot {
+    SELECT pg_drop_replication_slot('slot_creation_error');
+}
+
+session s2
+setup { SET synchronous_commit=on; }
+step s2_init {
+    SELECT 'init' FROM pg_create_logical_replication_slot('slot_creation_error', 'test_decoding');
+}
+
+# The tests first start a transaction with an xid assigned in s1, then create
+# a slot in s2. The slot creation waits for s1's transaction to end. Instead
+# we cancel / terminate s2.
+permutation s1_b s1_xid s2_init s1_view_slot s1_cancel_s2 s1_view_slot s1_c
+permutation s1_b s1_xid s2_init s1_c s1_view_slot s1_drop_slot # check slot creation still works
+permutation s1_b s1_xid s2_init s1_terminate_s2 s1_c s1_view_slot
+# can't run tests after this, due to s2's connection failure