alter_subscription_race.patch
application/octet-stream
Filename: alter_subscription_race.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/test/subscription/t/026_race.pl | 86 | 0 |
diff --git a/src/test/subscription/t/026_race.pl b/src/test/subscription/t/026_race.pl
new file mode 100644
index 0000000000..cbbe6c34e2
--- /dev/null
+++ b/src/test/subscription/t/026_race.pl
@@ -0,0 +1,86 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test subscriptions owned by non-superusers
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More;
+
+our $LOOPCOUNT = 100;
+plan tests => 2 * $LOOPCOUNT;
+my $result;
+
+# Setup
+
+my $node_publisher = PostgresNode->new('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+my $node_subscriber = PostgresNode->new('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+
+$node_publisher->safe_psql('postgres', qq(
+CREATE TABLE t (i INTEGER);
+ALTER TABLE t REPLICA IDENTITY FULL;
+CREATE PUBLICATION pub FOR TABLE t;
+));
+
+$node_subscriber->safe_psql('postgres', qq(
+CREATE TABLE t (i INTEGER);
+CREATE SUBSCRIPTION sub CONNECTION '$publisher_connstr' PUBLICATION pub;
+CREATE TABLE b (LIKE t);
+));
+
+# Wait for initial sync of all subscriptions.
+my $synced_query =
+ "SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('r', 's');";
+$node_subscriber->poll_query_until('postgres', $synced_query)
+ or die "Timed out while waiting for subscriber to synchronize data";
+
+# Upon first entry to this loop, the subscription is enabled
+foreach my $loop (1..$LOOPCOUNT)
+{
+ my $even = $loop * 2;
+ my $odd = ($loop * 2) + 1;
+
+ # The subscription is enabled. This even number is fair game for
+ # replication.
+ $node_publisher->safe_psql('postgres', "INSERT INTO t (i) VALUES ($even)");
+
+ # We may replicate the even number before the subscription is disabled, but
+ # maybe not.
+ $node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION sub DISABLE");
+
+ # The subscription is now disabled, but workers on the subscriber side may
+ # not have gotten the message yet. As such, this odd number may slip
+ # through.
+ $node_publisher->safe_psql('postgres', "INSERT INTO t (i) VALUES ($odd)");
+
+ # See if we can catch any odd numbers in the subscriber's copy of table t
+ $result = $node_subscriber->safe_psql('postgres',
+ "SELECT COUNT(*) FROM t WHERE i % 2 = 1");
+ is ($result, 0, "No odd numbers in subscriber copy of table t before delete on publisher");
+
+ # Clear out all values on the publisher side, so that the odd number cannot
+ # be replicated after we re-enable the subscription. Of course, it may have
+ # already slipped through, and it is also possible that the even number has
+ # not replicated yet.
+ #
+ # Since the publication only publishes INSERTs, this delete should only have
+ # effect on the publisher side.
+ $node_publisher->safe_psql('postgres', "DELETE FROM t WHERE i = $odd");
+
+ # Enable the subscription for the next loop. Note that at this point, the
+ # table is empty on the publisher side.
+ $node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION sub ENABLE");
+
+ # See if we can catch an odd number before the delete is propogated
+ $result = $node_subscriber->safe_psql('postgres',
+ "SELECT COUNT(*) FROM t WHERE i % 2 = 1");
+ is ($result, 0, "No odd numbers in subscriber copy of table t after delete on publisher");
+}