Skip to content

Commit dc622f8

Browse files
committed
fix: address second-round CodeRabbit findings on PR #13
- Dockerfile.consumer: run as non-root user - validator.py: only skip LOB unavailable markers in before images - validator.py: widen frontier on idle timeout to detect missing events
1 parent e9fc810 commit dc622f8

2 files changed

Lines changed: 38 additions & 12 deletions

File tree

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
FROM python:3.12-slim
2-
RUN pip install --no-cache-dir kafka-python-ng==2.2.3
2+
RUN pip install --no-cache-dir kafka-python-ng==2.2.3 \
3+
&& groupadd -r app && useradd -r -g app app \
4+
&& mkdir -p /app/data && chown app:app /app/data
5+
USER app

tests/dbz-twin/rac/validator.py

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,24 @@ def merge_lob_records(records):
8181
return merged_after, first_before
8282

8383

84-
def compare_values(lm_after, olr_after, table):
85-
"""Compare two normalized column dicts. Returns list of diff strings."""
84+
def compare_values(lm_cols, olr_cols, table, section='after'):
85+
"""Compare two normalized column dicts. Returns list of diff strings.
86+
87+
section: 'before' or 'after'. LOB unavailable markers are only skipped
88+
in 'before' images — Oracle doesn't provide old LOB values in redo.
89+
In 'after' images, unavailable markers indicate a real problem.
90+
"""
8691
diffs = []
87-
all_keys = set(lm_after.keys()) | set(olr_after.keys())
92+
all_keys = set(lm_cols.keys()) | set(olr_cols.keys())
8893
for key in sorted(all_keys):
8994
if key in ('EVENT_ID',):
9095
continue # Event ID verified separately
91-
va = lm_after.get(key)
92-
vb = olr_after.get(key)
93-
if key not in lm_after or key not in olr_after:
96+
va = lm_cols.get(key)
97+
vb = olr_cols.get(key)
98+
if key not in lm_cols or key not in olr_cols:
9499
continue # Supplemental logging differences
95-
if is_unavailable(va) or is_unavailable(vb):
96-
continue # LOB unavailable markers
100+
if section == 'before' and (is_unavailable(va) or is_unavailable(vb)):
101+
continue # LOB before-image unavailable (Oracle limitation)
97102
if va != vb:
98103
diffs.append(f" {key}: LM={va!r} OLR={vb!r}")
99104
return diffs
@@ -165,7 +170,25 @@ def main():
165170
if time.time() - last_new_events > IDLE_TIMEOUT:
166171
print(f"[validator] Idle timeout ({IDLE_TIMEOUT}s). "
167172
f"Final validation pass...", flush=True)
168-
break
173+
# Widen frontier to max of both sides per node to catch
174+
# truly missing events (one side never delivered them).
175+
for node_prefix in ('N1', 'N2'):
176+
lm_n = conn.execute(
177+
"SELECT MAX(event_id) FROM lm_events WHERE event_id LIKE ?",
178+
(f'{node_prefix}_%',)).fetchone()[0]
179+
olr_n = conn.execute(
180+
"SELECT MAX(event_id) FROM olr_events WHERE event_id LIKE ?",
181+
(f'{node_prefix}_%',)).fetchone()[0]
182+
if lm_n or olr_n:
183+
node_frontiers[node_prefix] = max(lm_n or '', olr_n or '')
184+
# Re-check if there's anything new with widened frontier
185+
any_new = any(
186+
nf > cursor_by_node.get(np, '')
187+
for np, nf in node_frontiers.items()
188+
)
189+
if not any_new:
190+
break
191+
# Fall through to validate the widened range
169192
else:
170193
continue
171194

@@ -252,8 +275,8 @@ def main():
252275
olr_after, olr_before = merge_lob_records(
253276
[dict(r) for r in olr_recs])
254277

255-
diffs = compare_values(lm_after, olr_after, lm_table)
256-
diffs.extend(compare_values(lm_before, olr_before, lm_table))
278+
diffs = compare_values(lm_after, olr_after, lm_table, 'after')
279+
diffs.extend(compare_values(lm_before, olr_before, lm_table, 'before'))
257280
if diffs:
258281
if is_lob:
259282
total_lob_known += 1

0 commit comments

Comments
 (0)