use strict;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;

my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->append_conf('postgresql.conf', qq{
wal_level = logical
wal_sender_timeout = 0
wal_receiver_timeout = 0
shared_buffers = 10GB
max_worker_processes = 32
max_parallel_maintenance_workers = 24
max_parallel_workers = 32
#log_min_messages = DEBUG2
});
$node_publisher->start;

my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
$node_subscriber->init;
$node_subscriber->append_conf('postgresql.conf', qq{
wal_level = logical
wal_sender_timeout = 0
wal_receiver_timeout = 0
shared_buffers = 10GB
max_worker_processes = 32
max_parallel_maintenance_workers = 24
max_parallel_workers = 32
#log_min_messages = DEBUG2
});
$node_subscriber->start;


$node_publisher->safe_psql(
    'postgres', qq(
    CREATE TABLE t1 (id int);
    CREATE PUBLICATION pub1 FOR TABLE t1;
));
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';

$node_subscriber->safe_psql(
    'postgres', qq(
    CREATE TABLE t1 (id int);
    CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1;
));

# Bump the query timeout to avoid false negatives on slow test systems.
my $psql_timeout_secs = 4 * $PostgreSQL::Test::Utils::timeout_default;

# Initiate 3 background sessions.
my $background_psql1 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql1->set_query_timer_restart();

my $background_psql2 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql2->set_query_timer_restart();

my $background_psql3 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql3->set_query_timer_restart();

my $background_psql4 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql4->set_query_timer_restart();

my $background_psql5 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql5->set_query_timer_restart();

my $background_psql6 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql6->set_query_timer_restart();

my $background_psql7 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql7->set_query_timer_restart();

my $background_psql8 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql8->set_query_timer_restart();

my $background_psql9 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql9->set_query_timer_restart();

my $background_psql10 = $node_publisher->background_psql(
    'postgres',
    on_error_stop => 0,
    timeout => $psql_timeout_secs);
$background_psql10->set_query_timer_restart();

    $background_psql1->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql2->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql4->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql5->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql6->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql7->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql8->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql9->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));

    $background_psql10->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));


my $sql = "";

for my $i (1..1000) {
    $sql .= "ALTER PUBLICATION pub1 DROP TABLE t1;\n";
    $sql .= "ALTER PUBLICATION pub1 ADD TABLE t1;\n";
}

$sql .= "COMMIT;";

for my $i(1...10000)
{
    for my $j(1...1000) {
        $background_psql3->query_safe("ALTER PUBLICATION pub1 DROP TABLE t1");
        $background_psql3->query_safe("ALTER PUBLICATION pub1 ADD TABLE t1");
    }

if ($i % 10 == 0) {
    $background_psql10->query_safe(
        qq($sql));
    $background_psql10->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));
}
elsif ($i % 9 == 0) {
    $background_psql9->query_safe(
        qq($sql));
    $background_psql9->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));
}
elsif ($i % 8 == 0) {
    $background_psql8->query_safe(
        qq($sql));
    $background_psql8->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));
}
elsif ($i % 7 == 0) {
    $background_psql7->query_safe(
        qq($sql));
    $background_psql7->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));
}
elsif ($i % 6 == 0) {
    $background_psql6->query_safe(
        qq($sql));
    $background_psql6->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));
}
elsif ($i % 5 == 0) {
    $background_psql6->query_safe(
        qq($sql));
    $background_psql6->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));
}
elsif ($i % 4 == 0) {
    $background_psql6->query_safe(
        qq($sql));
    $background_psql6->query_safe(
        qq(
        BEGIN;
        INSERT INTO t1 VALUES (1);
    ));
}
}

$background_psql1->quit;
$background_psql2->quit;
$background_psql3->quit;

done_testing();
