|
5 | 5 | use warnings;
|
6 | 6 | use PostgreSQL::Test::Utils;
|
7 | 7 | use PostgreSQL::Test::Cluster;
|
8 |
| -use Test::More tests => 31; |
| 8 | +use Test::More tests => 35; |
9 | 9 |
|
10 | 10 | program_help_ok('pg_receivewal');
|
11 | 11 | program_version_ok('pg_receivewal');
|
|
208 | 208 | "WAL streamed from the slot's restart_lsn");
|
209 | 209 | ok(-e "$slot_dir/$walfile_streamed",
|
210 | 210 | "WAL from the slot's restart_lsn has been archived");
|
| 211 | + |
| 212 | +# Test timeline switch using a replication slot, requiring a promoted |
| 213 | +# standby. |
| 214 | +my $backup_name = "basebackup"; |
| 215 | +$primary->backup($backup_name); |
| 216 | +my $standby = PostgreSQL::Test::Cluster->new("standby"); |
| 217 | +$standby->init_from_backup($primary, $backup_name, has_streaming => 1); |
| 218 | +$standby->start; |
| 219 | + |
| 220 | +# Create a replication slot on this new standby |
| 221 | +my $archive_slot = "archive_slot"; |
| 222 | +$standby->psql( |
| 223 | + '', |
| 224 | + "CREATE_REPLICATION_SLOT $archive_slot PHYSICAL (RESERVE_WAL)", |
| 225 | + replication => 1); |
| 226 | +# Wait for standby catchup |
| 227 | +$primary->wait_for_catchup($standby, 'replay', $primary->lsn('write')); |
| 228 | +# Get a walfilename from before the promotion to make sure it is archived |
| 229 | +# after promotion |
| 230 | +my $standby_slot = $standby->slot($archive_slot); |
| 231 | +my $replication_slot_lsn = $standby_slot->{'restart_lsn'}; |
| 232 | + |
| 233 | +# pg_walfile_name() is not supported while in recovery, so use the primary |
| 234 | +# to build the segment name. Both nodes are on the same timeline, so this |
| 235 | +# produces a segment name with the timeline we are switching from. |
| 236 | +my $walfile_before_promotion = |
| 237 | + $primary->safe_psql('postgres', |
| 238 | + "SELECT pg_walfile_name('$replication_slot_lsn');"); |
| 239 | +# Everything is setup, promote the standby to trigger a timeline switch. |
| 240 | +$standby->promote; |
| 241 | + |
| 242 | +# Force a segment switch to make sure at least one full WAL is archived |
| 243 | +# on the new timeline. |
| 244 | +my $walfile_after_promotion = $standby->safe_psql('postgres', |
| 245 | + "SELECT pg_walfile_name(pg_current_wal_insert_lsn());"); |
| 246 | +$standby->psql('postgres', 'INSERT INTO test_table VALUES (6);'); |
| 247 | +$standby->psql('postgres', 'SELECT pg_switch_wal();'); |
| 248 | +$nextlsn = |
| 249 | + $standby->safe_psql('postgres', 'SELECT pg_current_wal_insert_lsn();'); |
| 250 | +chomp($nextlsn); |
| 251 | +# This speeds up the operation. |
| 252 | +$standby->psql('postgres', 'INSERT INTO test_table VALUES (7);'); |
| 253 | + |
| 254 | +# Now try to resume from the slot after the promotion. |
| 255 | +my $timeline_dir = $primary->basedir . '/timeline_wal'; |
| 256 | +mkdir($timeline_dir); |
| 257 | + |
| 258 | +$standby->command_ok( |
| 259 | + [ |
| 260 | + 'pg_receivewal', '-D', $timeline_dir, '--verbose', |
| 261 | + '--endpos', $nextlsn, '--slot', $archive_slot, |
| 262 | + '--no-sync', '-n' |
| 263 | + ], |
| 264 | + "Stream some wal after promoting, resuming from the slot's position"); |
| 265 | +ok(-e "$timeline_dir/$walfile_before_promotion", |
| 266 | + "WAL segment $walfile_before_promotion archived after timeline jump"); |
| 267 | +ok(-e "$timeline_dir/$walfile_after_promotion", |
| 268 | + "WAL segment $walfile_after_promotion archived after timeline jump"); |
| 269 | +ok(-e "$timeline_dir/00000002.history", |
| 270 | + "timeline history file archived after timeline jump"); |
0 commit comments