|
410 | 410 | $node_primary3->stop;
|
411 | 411 | $node_standby3->stop;
|
412 | 412 |
|
| 413 | +# ============================================================================= |
| 414 | +# Testcase start: Check last_inactive_time property of the streaming standby's slot |
| 415 | +# |
| 416 | + |
| 417 | +# Initialize primary node |
| 418 | +my $primary4 = PostgreSQL::Test::Cluster->new('primary4'); |
| 419 | +$primary4->init(allows_streaming => 'logical'); |
| 420 | +$primary4->start; |
| 421 | + |
| 422 | +# Take backup |
| 423 | +$backup_name = 'my_backup4'; |
| 424 | +$primary4->backup($backup_name); |
| 425 | + |
| 426 | +# Create a standby linking to the primary using the replication slot |
| 427 | +my $standby4 = PostgreSQL::Test::Cluster->new('standby4'); |
| 428 | +$standby4->init_from_backup($primary4, $backup_name, has_streaming => 1); |
| 429 | + |
| 430 | +my $sb4_slot = 'sb4_slot'; |
| 431 | +$standby4->append_conf('postgresql.conf', "primary_slot_name = '$sb4_slot'"); |
| 432 | + |
| 433 | +my $slot_creation_time = $primary4->safe_psql( |
| 434 | + 'postgres', qq[ |
| 435 | + SELECT current_timestamp; |
| 436 | +]); |
| 437 | + |
| 438 | +$primary4->safe_psql( |
| 439 | + 'postgres', qq[ |
| 440 | + SELECT pg_create_physical_replication_slot(slot_name := '$sb4_slot'); |
| 441 | +]); |
| 442 | + |
| 443 | +# Get last_inactive_time value after the slot's creation. Note that the slot |
| 444 | +# is still inactive till it's used by the standby below. |
| 445 | +my $last_inactive_time = |
| 446 | + capture_and_validate_slot_last_inactive_time($primary4, $sb4_slot, $slot_creation_time); |
| 447 | + |
| 448 | +$standby4->start; |
| 449 | + |
| 450 | +# Wait until standby has replayed enough data |
| 451 | +$primary4->wait_for_catchup($standby4); |
| 452 | + |
| 453 | +# Now the slot is active so last_inactive_time value must be NULL |
| 454 | +is( $primary4->safe_psql( |
| 455 | + 'postgres', |
| 456 | + qq[SELECT last_inactive_time IS NULL FROM pg_replication_slots WHERE slot_name = '$sb4_slot';] |
| 457 | + ), |
| 458 | + 't', |
| 459 | + 'last inactive time for an active physical slot is NULL'); |
| 460 | + |
| 461 | +# Stop the standby to check its last_inactive_time value is updated |
| 462 | +$standby4->stop; |
| 463 | + |
| 464 | +# Let's restart the primary so that the last_inactive_time is set upon |
| 465 | +# loading the slot from the disk. |
| 466 | +$primary4->restart; |
| 467 | + |
| 468 | +is( $primary4->safe_psql( |
| 469 | + 'postgres', |
| 470 | + qq[SELECT last_inactive_time > '$last_inactive_time'::timestamptz FROM pg_replication_slots WHERE slot_name = '$sb4_slot' AND last_inactive_time IS NOT NULL;] |
| 471 | + ), |
| 472 | + 't', |
| 473 | + 'last inactive time for an inactive physical slot is updated correctly'); |
| 474 | + |
| 475 | +$standby4->stop; |
| 476 | + |
| 477 | +# Testcase end: Check last_inactive_time property of the streaming standby's slot |
| 478 | +# ============================================================================= |
| 479 | + |
| 480 | +# ============================================================================= |
| 481 | +# Testcase start: Check last_inactive_time property of the logical subscriber's slot |
| 482 | +my $publisher4 = $primary4; |
| 483 | + |
| 484 | +# Create subscriber node |
| 485 | +my $subscriber4 = PostgreSQL::Test::Cluster->new('subscriber4'); |
| 486 | +$subscriber4->init; |
| 487 | + |
| 488 | +# Setup logical replication |
| 489 | +my $publisher4_connstr = $publisher4->connstr . ' dbname=postgres'; |
| 490 | +$publisher4->safe_psql('postgres', "CREATE PUBLICATION pub FOR ALL TABLES"); |
| 491 | + |
| 492 | +$slot_creation_time = $publisher4->safe_psql( |
| 493 | + 'postgres', qq[ |
| 494 | + SELECT current_timestamp; |
| 495 | +]); |
| 496 | + |
| 497 | +my $lsub4_slot = 'lsub4_slot'; |
| 498 | +$publisher4->safe_psql('postgres', |
| 499 | + "SELECT pg_create_logical_replication_slot(slot_name := '$lsub4_slot', plugin := 'pgoutput');" |
| 500 | +); |
| 501 | + |
| 502 | +# Get last_inactive_time value after the slot's creation. Note that the slot |
| 503 | +# is still inactive till it's used by the subscriber below. |
| 504 | +$last_inactive_time = |
| 505 | + capture_and_validate_slot_last_inactive_time($publisher4, $lsub4_slot, $slot_creation_time); |
| 506 | + |
| 507 | +$subscriber4->start; |
| 508 | +$subscriber4->safe_psql('postgres', |
| 509 | + "CREATE SUBSCRIPTION sub CONNECTION '$publisher4_connstr' PUBLICATION pub WITH (slot_name = '$lsub4_slot', create_slot = false)" |
| 510 | +); |
| 511 | + |
| 512 | +# Wait until subscriber has caught up |
| 513 | +$subscriber4->wait_for_subscription_sync($publisher4, 'sub'); |
| 514 | + |
| 515 | +# Now the slot is active so last_inactive_time value must be NULL |
| 516 | +is( $publisher4->safe_psql( |
| 517 | + 'postgres', |
| 518 | + qq[SELECT last_inactive_time IS NULL FROM pg_replication_slots WHERE slot_name = '$lsub4_slot';] |
| 519 | + ), |
| 520 | + 't', |
| 521 | + 'last inactive time for an active logical slot is NULL'); |
| 522 | + |
| 523 | +# Stop the subscriber to check its last_inactive_time value is updated |
| 524 | +$subscriber4->stop; |
| 525 | + |
| 526 | +# Let's restart the publisher so that the last_inactive_time is set upon |
| 527 | +# loading the slot from the disk. |
| 528 | +$publisher4->restart; |
| 529 | + |
| 530 | +is( $publisher4->safe_psql( |
| 531 | + 'postgres', |
| 532 | + qq[SELECT last_inactive_time > '$last_inactive_time'::timestamptz FROM pg_replication_slots WHERE slot_name = '$lsub4_slot' AND last_inactive_time IS NOT NULL;] |
| 533 | + ), |
| 534 | + 't', |
| 535 | + 'last inactive time for an inactive logical slot is updated correctly'); |
| 536 | + |
| 537 | +# Testcase end: Check last_inactive_time property of the logical subscriber's slot |
| 538 | +# ============================================================================= |
| 539 | + |
| 540 | +$publisher4->stop; |
| 541 | +$subscriber4->stop; |
| 542 | + |
| 543 | +# Capture and validate last_inactive_time of a given slot. |
| 544 | +sub capture_and_validate_slot_last_inactive_time |
| 545 | +{ |
| 546 | + my ($node, $slot_name, $slot_creation_time) = @_; |
| 547 | + |
| 548 | + my $last_inactive_time = $node->safe_psql('postgres', |
| 549 | + qq(SELECT last_inactive_time FROM pg_replication_slots |
| 550 | + WHERE slot_name = '$slot_name' AND last_inactive_time IS NOT NULL;) |
| 551 | + ); |
| 552 | + |
| 553 | + # Check that the captured time is sane |
| 554 | + is( $node->safe_psql( |
| 555 | + 'postgres', |
| 556 | + qq[SELECT '$last_inactive_time'::timestamptz > to_timestamp(0) AND |
| 557 | + '$last_inactive_time'::timestamptz >= '$slot_creation_time'::timestamptz;] |
| 558 | + ), |
| 559 | + 't', |
| 560 | + "last inactive time for an active slot $slot_name is sane"); |
| 561 | + |
| 562 | + return $last_inactive_time; |
| 563 | +} |
| 564 | + |
413 | 565 | done_testing();
|
0 commit comments