Skip to content

fix: per-node origin name translation in table diff and merkle tree#117

Merged
mason-sharp merged 1 commit intomainfrom
fix/pg-node-origin
Apr 21, 2026
Merged

fix: per-node origin name translation in table diff and merkle tree#117
mason-sharp merged 1 commit intomainfrom
fix/pg-node-origin

Conversation

@mason-sharp
Copy link
Copy Markdown
Member

NodeOriginNames was loaded from one random pool and used to translate roidents from all nodes. In native PG, roidents are node-local, so the same roident maps to different subscription names on different nodes. This caused intermittent preserve-origin repair failures when the diff happened to load origin names from the wrong node.

Change NodeOriginNames to map[string]map[string]string (nodeName → roident → name). Load from every pool. Pass the originating node name into withSpockMetadata so each row's roident is resolved correctly.

NodeOriginNames was loaded from one random pool and used to translate
roidents from all nodes. In native PG, roidents are node-local, so
the same roident maps to different subscription names on different
nodes. This caused intermittent preserve-origin repair failures when
the diff happened to load origin names from the wrong node.

Change NodeOriginNames to map[string]map[string]string (nodeName →
roident → name). Load from every pool. Pass the originating node name
into withSpockMetadata so each row's roident is resolved correctly.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

📝 Walkthrough

Walkthrough

The changes refactor origin-name mappings in table and merkle tree diff tasks from a single global map to per-node nested maps, enabling node-specific origin lookups and improving failure tolerance when loading node-specific data.

Changes

Cohort / File(s) Summary
Core Data Structure Updates
internal/consistency/diff/table_diff.go, internal/consistency/mtree/merkle.go
Changed NodeOriginNames from map[string]string to map[string]map[string]string. Added flatNodeOriginNames() to merge per-node mappings. Reworked initialization to load and store mappings per node, tolerating per-node failures and erroring only if no nodes succeeded. Updated translation logic to use node-specific mappings.
Method Signature Updates
internal/consistency/diff/table_diff.go, internal/consistency/diff/table_rerun.go
Updated withSpockMetadata() to accept nodeName parameter for per-node origin translation. Modified call sites in table_rerun.go to pass node identifiers when processing diff rows.
Test Coverage
internal/consistency/diff/table_diff_origin_test.go
Updated existing tests to use nested NodeOriginNames structure. Added TestWithSpockMetadata_PerNodeTranslation and TestFlatNodeOriginNames_MergesAllNodes to validate per-node translation and flattening behavior.

Poem

🐰 Each node now knows its origin's name,
No more confusion, no global claim,
We flatten, merge, and translate true,
Per-node mappings through and through! 🌳

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: fixing per-node origin name translation in two key components (table diff and merkle tree), which directly matches the core bug fix described in the pull request.
Description check ✅ Passed The description is directly related to the changeset, explaining the bug (roidents are node-local), the fix (nested map structure), and the behavior change (per-node loading and translation).

✏️ 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 fix/pg-node-origin

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 7 complexity · -2 duplication

Metric Results
Complexity 7
Duplication -2

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

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)
internal/consistency/diff/table_diff.go (1)

225-274: ⚠️ Potential issue | 🟠 Major

Avoid resolving --against-origin through a flattened node-local map.

Line 244 collapses per-node origin IDs back into one ID, then Line 297 applies that single ID to every node. In native PostgreSQL, the same roident can mean different origins per node, so an origin name can resolve from one node and then incorrectly include/exclude rows on another node where that ID means something else.

Keep the resolved origin scoped per node and build node-specific filters for hashing, fetching, row-count estimation, and range generation; or fail fast when the requested origin cannot be resolved unambiguously across selected nodes. Also tighten TestFlatNodeOriginNames_MergesAllNodes so conflicting flattened mappings are not accepted as valid behavior.

Based on learnings, GetNodeOriginNames switches between Spock node IDs and native pg_replication_origin IDs depending on Spock extension presence.

Also applies to: 292-297

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/consistency/diff/table_diff.go` around lines 225 - 274, The current
approach in flatNodeOriginNames() and resolveAgainstOrigin() incorrectly
flattens NodeOriginNames into a single map and then sets a single
resolvedAgainstOrigin ID for all nodes; instead preserve per-node resolution:
change resolveAgainstOrigin() to iterate NodeOriginNames and produce a per-node
map (e.g. resolvedAgainstOriginByNode) or return an error if the requested
AgainstOrigin does not unambiguously resolve for every selected node, use those
per-node IDs when building filters/hashes/fetches/range generation, and do not
overwrite a single t.resolvedAgainstOrigin; also update
TestFlatNodeOriginNames_MergesAllNodes to assert conflicts across nodes are
rejected (or that per-node mappings are preserved) and review GetNodeOriginNames
usage to ensure it supplies node-scoped IDs (Spock vs native
pg_replication_origin) rather than relying on a flattened global mapping.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@internal/consistency/diff/table_diff.go`:
- Around line 225-274: The current approach in flatNodeOriginNames() and
resolveAgainstOrigin() incorrectly flattens NodeOriginNames into a single map
and then sets a single resolvedAgainstOrigin ID for all nodes; instead preserve
per-node resolution: change resolveAgainstOrigin() to iterate NodeOriginNames
and produce a per-node map (e.g. resolvedAgainstOriginByNode) or return an error
if the requested AgainstOrigin does not unambiguously resolve for every selected
node, use those per-node IDs when building filters/hashes/fetches/range
generation, and do not overwrite a single t.resolvedAgainstOrigin; also update
TestFlatNodeOriginNames_MergesAllNodes to assert conflicts across nodes are
rejected (or that per-node mappings are preserved) and review GetNodeOriginNames
usage to ensure it supplies node-scoped IDs (Spock vs native
pg_replication_origin) rather than relying on a flattened global mapping.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 59f2b269-28b7-405c-9c26-58187ba79e71

📥 Commits

Reviewing files that changed from the base of the PR and between 34f13e0 and ffc0ca6.

📒 Files selected for processing (4)
  • internal/consistency/diff/table_diff.go
  • internal/consistency/diff/table_diff_origin_test.go
  • internal/consistency/diff/table_rerun.go
  • internal/consistency/mtree/merkle.go

@ibrarahmad ibrarahmad self-requested a review April 21, 2026 21:10
@mason-sharp mason-sharp merged commit d4f4bfe into main Apr 21, 2026
3 checks passed
@mason-sharp mason-sharp deleted the fix/pg-node-origin branch April 21, 2026 21:11
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.

2 participants