mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-14 22:20:30 +03:00

This avoids restarting the postgresql server, when only ensureDatabases or ensureUsers have been changed. It will also allow to properly wait for recovery to finish later. To wait for "postgresql is ready" in other services, we now provide a postgresql.target. Resolves #400018 Co-authored-by: Marcel <me@m4rc3l.de>
111 lines
4 KiB
Nix
111 lines
4 KiB
Nix
{
|
|
pkgs,
|
|
makeTest,
|
|
genTests,
|
|
}:
|
|
|
|
let
|
|
inherit (pkgs) lib;
|
|
|
|
makeTestFor =
|
|
package:
|
|
let
|
|
postgresqlDataDir = "/var/lib/postgresql/${package.psqlSchema}";
|
|
replicationUser = "wal_receiver_user";
|
|
replicationSlot = "wal_receiver_slot";
|
|
replicationConn = "postgresql://${replicationUser}@localhost";
|
|
baseBackupDir = "/var/cache/wals/pg_basebackup";
|
|
walBackupDir = "/var/cache/wals/pg_wal";
|
|
recoveryFile = pkgs.writeTextDir "recovery.signal" "";
|
|
in
|
|
makeTest {
|
|
name = "postgresql-wal-receiver-${package.name}";
|
|
meta.maintainers = with lib.maintainers; [ euxane ];
|
|
|
|
nodes.machine =
|
|
{ ... }:
|
|
{
|
|
systemd.tmpfiles.rules = [
|
|
"d /var/cache/wals 0750 postgres postgres - -"
|
|
];
|
|
|
|
services.postgresql = {
|
|
inherit package;
|
|
enable = true;
|
|
settings = {
|
|
max_replication_slots = 10;
|
|
max_wal_senders = 10;
|
|
recovery_end_command = "touch recovery.done";
|
|
restore_command = "cp ${walBackupDir}/%f %p";
|
|
wal_level = "archive"; # alias for replica on pg >= 9.6
|
|
};
|
|
authentication = ''
|
|
host replication ${replicationUser} all trust
|
|
'';
|
|
initialScript = pkgs.writeText "init.sql" ''
|
|
create user ${replicationUser} replication;
|
|
select * from pg_create_physical_replication_slot('${replicationSlot}');
|
|
'';
|
|
};
|
|
|
|
services.postgresqlWalReceiver.receivers.main = {
|
|
postgresqlPackage = package;
|
|
connection = replicationConn;
|
|
slot = replicationSlot;
|
|
directory = walBackupDir;
|
|
};
|
|
# This is only to speedup test, it isn't time racing. Service is set to autorestart always,
|
|
# default 60sec is fine for real system, but is too much for a test
|
|
systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = lib.mkForce 5;
|
|
systemd.services.postgresql.serviceConfig.ReadWritePaths = [ "/var/cache/wals" ];
|
|
};
|
|
|
|
testScript = ''
|
|
# make an initial base backup
|
|
machine.wait_for_unit("postgresql.target")
|
|
machine.wait_for_unit("postgresql-wal-receiver-main")
|
|
# WAL receiver healthchecks PG every 5 seconds, so let's be sure they have connected each other
|
|
# required only for 9.4
|
|
machine.sleep(5)
|
|
machine.succeed(
|
|
"${package}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}"
|
|
)
|
|
|
|
# create a dummy table with 100 records
|
|
machine.succeed(
|
|
"sudo -u postgres psql --command='create table dummy as select * from generate_series(1, 100) as val;'"
|
|
)
|
|
|
|
# stop postgres and destroy data
|
|
machine.systemctl("stop postgresql")
|
|
machine.systemctl("stop postgresql-wal-receiver-main")
|
|
machine.succeed("rm -r ${postgresqlDataDir}/{base,global,pg_*}")
|
|
|
|
# restore the base backup
|
|
machine.succeed(
|
|
"cp -r ${baseBackupDir}/* ${postgresqlDataDir} && chown postgres:postgres -R ${postgresqlDataDir}"
|
|
)
|
|
|
|
# prepare WAL and recovery
|
|
machine.succeed("chmod a+rX -R ${walBackupDir}")
|
|
machine.execute(
|
|
"for part in ${walBackupDir}/*.partial; do mv $part ''${part%%.*}; done"
|
|
) # make use of partial segments too
|
|
machine.succeed(
|
|
"cp ${recoveryFile}/* ${postgresqlDataDir}/ && chmod 666 ${postgresqlDataDir}/recovery*"
|
|
)
|
|
|
|
# replay WAL
|
|
machine.systemctl("start postgresql")
|
|
machine.wait_for_file("${postgresqlDataDir}/recovery.done")
|
|
machine.systemctl("restart postgresql")
|
|
machine.wait_for_unit("postgresql.target")
|
|
|
|
# check that our records have been restored
|
|
machine.succeed(
|
|
"test $(sudo -u postgres psql --pset='pager=off' --tuples-only --command='select count(distinct val) from dummy;') -eq 100"
|
|
)
|
|
'';
|
|
};
|
|
in
|
|
genTests { inherit makeTestFor; }
|