Skip to content

Make heap apply retry loop configurable via spock.read_retry_count#475

Open
ibrarahmad wants to merge 1 commit into
mainfrom
SPOC-553
Open

Make heap apply retry loop configurable via spock.read_retry_count#475
ibrarahmad wants to merge 1 commit into
mainfrom
SPOC-553

Conversation

@ibrarahmad
Copy link
Copy Markdown
Contributor

spock_apply_heap_update() and spock_apply_heap_delete() hardcoded the retry count at 5 when the local tuple could not be found. Expose this as a GUC (default 5, range 0..100, PGC_SIGHUP) so deployments hitting out-of-order arrivals can tune the loop without rebuilding.

spock_apply_heap_update() and spock_apply_heap_delete() hardcoded the
retry count at 5 when the local tuple could not be found.  Expose this
as a GUC (default 5, range 0..100, PGC_SIGHUP) so deployments hitting
out-of-order arrivals can tune the loop without rebuilding.
@ibrarahmad ibrarahmad requested a review from mason-sharp May 20, 2026 12:43
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a new spock.read_retry_count GUC parameter to make the apply worker's retry behavior configurable when local tuples are not yet visible during heap UPDATE/DELETE operations. The retry limit changes from hardcoded 5 to a runtime-configurable value (0–100, default 5).

Changes

Configurable Read Retry Count

Layer / File(s) Summary
GUC declaration and registration
include/spock.h, src/spock.c
Exports spock_read_retry_count global variable and registers the SIGHUP-scoped GUC with bounds (0–100), default value (5), and descriptive help text.
Apply path integration
src/spock_apply_heap.c
Includes the spock header and replaces hardcoded retry limit with the spock_read_retry_count variable in both heap update and heap delete apply paths.
End-to-end TAP test
tests/tap/t/030_read_retry_count_guc.pl
Validates GUC default value, pg_settings metadata, runtime updates via ALTER SYSTEM SET and reload, and range boundary enforcement.

Poem

🐰 A retry count that dances free,
Not fixed at five, but up to thee!
From zero to a hundred fair,
Apply workers skip and care.
Configuration hops with glee! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: making the heap apply retry loop configurable via a new GUC parameter.
Description check ✅ Passed The description is directly related to the changeset, explaining the motivation and implementation details of exposing the hardcoded retry count as a configurable GUC.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch SPOC-553

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codacy-production
Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/spock_apply_heap.c (1)

972-989: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Initialize lookup state and always perform an initial tuple read before retries.

With spock.read_retry_count = 0, these loops never execute, so found is read uninitialized and the code may take an arbitrary branch. It also skips the initial local tuple lookup entirely.

💡 Proposed fix
@@
-	bool		found;
+	bool		found = false;
@@
-	retry = 0;
-	while (retry < spock_read_retry_count)
-	{
-		found = FindReplTupleInLocalRel(edata, relinfo->ri_RelationDesc,
-										edata->targetRel->idxoid,
-										remoteslot, &localslot,
-										false);
-		if (found)
-			break;
-
-		wait_for_previous_transaction();
-		retry++;
-	}
+	found = FindReplTupleInLocalRel(edata, relinfo->ri_RelationDesc,
+									edata->targetRel->idxoid,
+									remoteslot, &localslot,
+									false);
+	retry = 0;
+	while (!found && retry < spock_read_retry_count)
+	{
+		wait_for_previous_transaction();
+		retry++;
+		found = FindReplTupleInLocalRel(edata, relinfo->ri_RelationDesc,
+										edata->targetRel->idxoid,
+										remoteslot, &localslot,
+										false);
+	}

Apply the same pattern in both spock_apply_heap_update() and spock_apply_heap_delete().

Also applies to: 1089-1106

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/spock_apply_heap.c` around lines 972 - 989, Initialize the lookup state
and perform an initial FindReplTupleInLocalRel call before entering the retry
loop to avoid reading the uninitialized variable `found` when
`spock_read_retry_count` is 0; specifically in functions
`spock_apply_heap_update()` and `spock_apply_heap_delete()` set `retry = 0`,
initialize `found = false` (or equivalent), call `FindReplTupleInLocalRel(edata,
relinfo->ri_RelationDesc, edata->targetRel->idxoid, remoteslot, &localslot,
false)` once and handle the result before entering the while (retry <
spock_read_retry_count) loop, then keep the existing
wait_for_previous_transaction() / retry++ logic for subsequent attempts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/spock_apply_heap.c`:
- Around line 972-989: Initialize the lookup state and perform an initial
FindReplTupleInLocalRel call before entering the retry loop to avoid reading the
uninitialized variable `found` when `spock_read_retry_count` is 0; specifically
in functions `spock_apply_heap_update()` and `spock_apply_heap_delete()` set
`retry = 0`, initialize `found = false` (or equivalent), call
`FindReplTupleInLocalRel(edata, relinfo->ri_RelationDesc,
edata->targetRel->idxoid, remoteslot, &localslot, false)` once and handle the
result before entering the while (retry < spock_read_retry_count) loop, then
keep the existing wait_for_previous_transaction() / retry++ logic for subsequent
attempts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e3e32207-725a-4461-8734-9ffbaae7466f

📥 Commits

Reviewing files that changed from the base of the PR and between 3886058 and 135a35a.

📒 Files selected for processing (4)
  • include/spock.h
  • src/spock.c
  • src/spock_apply_heap.c
  • tests/tap/t/030_read_retry_count_guc.pl

Comment thread src/spock.c
"concurrently-applying transaction to finish, then "
"searches the local relation again. Set to 0 to disable "
"retries (the row-missing path runs immediately). "
"Used in spock_apply_heap_update and "
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little bit too verbose, no need to mention which functions. Can you please shorten? Something like the first 4 lines and the "Set to 0" sentence?

Copy link
Copy Markdown
Contributor

@danolivo danolivo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants