Skip to content

Commit 2c94873

Browse files
mason-sharpclaude
andcommitted
Track per-node repset membership in repset-diff
Report tables that are in the repset on some nodes but not others. All tables are still diffed (the data exists on all nodes), but asymmetric repset membership is now surfaced in the summary. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2f02e5f commit 2c94873

2 files changed

Lines changed: 46 additions & 11 deletions

File tree

internal/consistency/diff/repset_diff.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ func (c *RepsetDiffCmd) RunChecks(skipValidation bool) error {
135135
// In a uni-directional setup the repset may only exist on the publisher, but
136136
// the tables themselves exist on all nodes, so we still diff them across
137137
// every node.
138-
tableSet := make(map[string]bool)
139-
var nodesWithRepset int
138+
tablePresence := make(map[string]map[string]bool) // table -> {nodeName: true}
139+
var repsetNodeNames []string
140140

141141
for _, nodeInfo := range c.clusterNodes {
142142
nodeName := nodeInfo["Name"].(string)
@@ -165,7 +165,7 @@ func (c *RepsetDiffCmd) RunChecks(skipValidation bool) error {
165165
logger.Warn("repset %s not found on node %s, skipping for table discovery", c.RepsetName, nodeName)
166166
continue
167167
}
168-
nodesWithRepset++
168+
repsetNodeNames = append(repsetNodeNames, nodeName)
169169

170170
tables, err := queries.GetTablesInRepSet(c.Ctx, pool, c.RepsetName)
171171
pool.Close()
@@ -174,21 +174,47 @@ func (c *RepsetDiffCmd) RunChecks(skipValidation bool) error {
174174
}
175175

176176
for _, t := range tables {
177-
tableSet[t] = true
177+
if tablePresence[t] == nil {
178+
tablePresence[t] = make(map[string]bool)
179+
}
180+
tablePresence[t][nodeName] = true
178181
}
179182
}
180183

181-
if nodesWithRepset == 0 {
184+
if len(repsetNodeNames) == 0 {
182185
return fmt.Errorf("repset %s not found on any node", c.RepsetName)
183186
}
184187

188+
// Build the full table list (union) and track tables not in the repset
189+
// on every node. All tables are still diffed (the data exists on all
190+
// nodes), but asymmetric repset membership is reported in the summary.
185191
var allTables []string
186-
for t := range tableSet {
187-
allTables = append(allTables, t)
192+
var missingTables []MissingTableInfo
193+
for table, presence := range tablePresence {
194+
allTables = append(allTables, table)
195+
if len(presence) < len(repsetNodeNames) {
196+
var presentOn, missingFrom []string
197+
for _, n := range repsetNodeNames {
198+
if presence[n] {
199+
presentOn = append(presentOn, n)
200+
} else {
201+
missingFrom = append(missingFrom, n)
202+
}
203+
}
204+
missingTables = append(missingTables, MissingTableInfo{
205+
Table: table,
206+
PresentOn: presentOn,
207+
MissingFrom: missingFrom,
208+
})
209+
}
188210
}
189211
sort.Strings(allTables)
212+
sort.Slice(missingTables, func(i, j int) bool {
213+
return missingTables[i].Table < missingTables[j].Table
214+
})
190215

191216
c.tableList = allTables
217+
c.missingTables = missingTables
192218

193219
if len(c.tableList) == 0 {
194220
return fmt.Errorf("no tables found in repset %s", c.RepsetName)

tests/integration/repset_diff_summary_test.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,20 @@ func TestRepsetDiff_UniDirectional(t *testing.T) {
8888
// still compares data across both nodes.
8989
require.NoError(t, diffErr)
9090

91+
// Extract the summary section for precise assertions.
92+
summarySection := extractSummarySection(t, logOutput)
93+
9194
// The table should have been compared and found identical.
92-
assert.Contains(t, logOutput, "table(s) are identical",
93-
"summary should show identical tables")
94-
assert.Contains(t, logOutput, qualifiedTableName,
95-
"the uni-directional table should appear in the summary")
95+
identicalSection := extractBetween(summarySection, "table(s) are identical:", "table(s)")
96+
assert.Contains(t, identicalSection, qualifiedTableName,
97+
"the uni-directional table should be compared and found identical")
98+
99+
// The asymmetric repset membership should be reported.
100+
missingSection := extractBetween(summarySection, "not present on all nodes:", "table(s)")
101+
assert.Contains(t, missingSection, qualifiedTableName,
102+
"table should be reported as not in repset on all nodes")
103+
assert.Contains(t, missingSection, fmt.Sprintf("missing from [%s]", serviceN2),
104+
"should indicate which node is missing the table in its repset")
96105
}
97106

98107
// TestRepsetDiff_Summary verifies that the repset-diff summary correctly

0 commit comments

Comments
 (0)