Conversation
📝 WalkthroughWalkthroughExpanded a single test file from 25 to 43 tests to cover DISCARD, TRANSDISCARD, and SUB_DISABLE exception-handling modes with multi-phase subscription setup, per-mode transaction scenarios, replication waits, and exception_log validations. Changes
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@tests/tap/t/013_exception_handling.pl`:
- Around line 303-397: The test's intent is contradictory: the header for Test
4a says exception log entries should be LOST, but assertions check for existence
(deferred_exception_count > 0 and deferred_row eq 't'); decide which behavior is
correct and make the file consistent by updating both comments and assertions:
if the expected behavior is that logs are lost and data not applied, change the
header and inline comments to state "exception logs are LOST and data not
applied" and replace assertions using deferred_exception_count and deferred_row
with exact equality checks (is(deferred_exception_count, '0', ...) and
is(deferred_row, 'f', ...)); if the expected behavior is that the apply worker
handles the deferred trigger and logs survive and data is applied, change the
header/comments to state "exception logs survive and data applied" and keep or
strengthen the assertions to explicitly assert existence
(isnt(deferred_exception_count, '0', ...) or is(gt,0) and is(deferred_row, 't',
...)); also ensure messaging strings in the pass/diag lines around test_deferred
and abort_at_commit_fn reflect the chosen expectation.
- Around line 280-296: The test continues when scalar_query(...) returns undef
for $skip_lsn which causes downstream calls to psql_or_bail("SELECT
spock.sub_alter_skiplsn('exception_test_sub', '$skip_lsn')") and
psql_or_bail("SELECT spock.sub_enable('exception_test_sub', true)") to fail;
update the test after the ok($skip_lsn, ...) check to bail out immediately when
$skip_lsn is falsey (e.g., call bail/die or skip the remaining steps) so that
you don't interpolate an undef into sub_alter_skiplsn/sub_enable and you surface
the original extraction failure from scalar_query rather than cascading errors.
Ensure you reference the scalar_query call and the $skip_lsn variable when
adding the early exit.
🧹 Nitpick comments (3)
tests/tap/t/013_exception_handling.pl (3)
130-131: Backtickpsqlcalls bypass test helpers and may fail silently.Lines 130, 196, and 263 invoke
psqldirectly via backticks instead of usingSpockTesthelper functions. If the connection fails (e.g., missing.pgpass, wrong port), the error is silently swallowed into$log_outputand only visible indiag. Consider using the existing helper or at minimum checking$?after the backtick call.
50-50: Sleep-based synchronization is fragile and adds ~53 seconds of fixed wait.The test relies on fixed
sleepcalls (ranging from 2–8 seconds each, totaling ~53s) for replication sync. Under CI load or slower machines, these may be insufficient, causing flaky failures. On fast machines, they waste time unnecessarily.Consider replacing with a poll-and-retry loop that checks the expected condition (e.g., table exists on subscriber, row count matches, subscription status) with a timeout. For example:
# Poll for a condition with timeout my $timeout = 30; my $start = time(); while (time() - $start < $timeout) { my $result = scalar_query(2, "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'test_discard')"); last if $result eq 't'; sleep 1; }This would make the tests both faster and more reliable.
Also applies to: 84-84, 105-105, 235-235, 328-328, 368-368
211-215: Inconsistent subscription re-enable: direct UPDATE vs. API function.Lines 212–214 toggle the subscription by directly updating
spock.subscription, while line 294 uses the proper APIspock.sub_enable(...). Direct table manipulation may skip internal bookkeeping (e.g., worker restart signals, state transitions) that the API function handles.Unless there's a specific reason the API can't be used here, prefer using the API consistently:
Suggested fix
-psql_or_bail(2, "UPDATE spock.subscription SET sub_enabled = false WHERE sub_name = 'exception_test_sub'"); +psql_or_bail(2, "SELECT spock.sub_disable('exception_test_sub')"); system_or_bail 'sleep', '2'; -psql_or_bail(2, "UPDATE spock.subscription SET sub_enabled = true WHERE sub_name = 'exception_test_sub'"); +psql_or_bail(2, "SELECT spock.sub_enable('exception_test_sub', true)");
Test coverage for all three exception handling modes: - DISCARD: Failed operations skipped, transaction continues - TRANSDISCARD: Entire transaction rolled back on failure - SUB_DISABLE: Subscription disabled on exception Also tests exception log transactional behavior with deferred constraint triggers to verify apply worker handles errors gracefully and exception logs survive. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4791696 to
86f3e69
Compare
Test coverage for all three exception handling modes:
Also tests exception log transactional behavior with deferred constraint triggers to verify logs survive transaction aborts.