use strict;
use warnings FATAL => 'all';

use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;

use IPC::Run;
use threads;
use threads::shared;

sub bgactivity
{
	my @args = @_;
	my ($n, $port, $db_name) = @args;
	$SIG{'KILL'} = sub { print("Thread killed.\n"); threads->exit(); };

	my $try = 1;
	while (1)
	{
		my ($stdout, $stderr);
		my $cmd = [ 'psql', '-h', $ENV{'PGHOST'}, '-p', $port, '-d', $db_name, '-c', "INSERT INTO t VALUES (1000 * $n + $try, 'background activity');" ];
		my $result = IPC::Run::run($cmd, '>', \$stdout, '2>', \$stderr);
		$try += 1;
		sleep(0.001);
	}
}

# Set up two replication nodes, which will switch roles.

my $node1 = PostgreSQL::Test::Cluster->new("node1");
$node1->init(allows_streaming => 1);
$node1->start;
$node1->backup('initial_backup');

my $node2 = PostgreSQL::Test::Cluster->new('node2');
$node2->init_from_backup($node1, 'initial_backup', has_streaming => 1);
$node2->start;

$node1->psql('postgres', "ALTER SYSTEM SET synchronous_standby_names = 'node2'; SELECT pg_reload_conf()");
$node2->psql('postgres', "ALTER SYSTEM SET synchronous_standby_names = 'node1'; SELECT pg_reload_conf()");

$node1->psql('postgres', "CREATE TABLE t(id int, message text)");

my $numthreads = 2;
my @threads;
foreach my $ti (1 .. $numthreads)
{
    push @threads, threads->create('bgactivity', $ti, $node1->port, 'postgres');
}

for (my $i = 1; $i <= 20; $i++)
{
my ($primary, $standby) = ($node1, $node2);

$primary->safe_psql('postgres', "INSERT INTO t VALUES ($i, 'inserted on node1');");

# change roles
$primary->teardown_node;
$standby->promote;

$primary->enable_streaming($standby);
$primary->start;

($primary, $standby) = ($node2, $node1);

$primary->safe_psql('postgres', "INSERT INTO t VALUES ($i, 'inserted on node2');");

# change roles back
$primary->teardown_node;
$standby->promote;

$primary->enable_streaming($standby);
$primary->start;

ok(1);
}

for my $thread (@threads)
{
	$thread->kill('KILL')->detach;
}

done_testing();
