fix: prevent catalog crash on duplicate business event channels#533
Conversation
Cloud-portal has duplicate business event channels in cached AsyncAPI documents, which caused a UNIQUE constraint crash on contract_messages that killed the entire catalog build (blocking REFRESH CATALOG FULL). Fix: INSERT OR IGNORE to tolerate duplicate rows defensively.
04526ae to
6f7d86b
Compare
AI Code ReviewWhat Looks Good
RecommendationApprove the PR. The changes are low-risk, follow established patterns, and resolve the crash scenario. The manual test steps in the test plan should be completed before merging, but the passing unit tests and localized nature of the changes support approval. No modifications to MDL syntax or full-stack pipeline were required for this internal catalog fix. Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
AI Code ReviewReview SummaryMinor Issues
What Looks Good
RecommendationApprove the PR once the test plan items are completed. The fix is technically sound and addresses the root cause, but the manual verification steps are important for confirming the solution works in the target scenario (Cloud Portal MPR with duplicate business event channels). Please run Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
AI Code ReviewCritical IssuesNone found Moderate IssuesNone found Minor IssuesNone found What Looks GoodThe PR makes a minimal, targeted fix to prevent catalog crashes from duplicate business event channels:
The PR correctly implements a defensive programming approach for the catalog refresh operation where duplicate data from external sources (Cloud Portal) is expected but shouldn't halt the entire process. RecommendationApprove the PR. The change is minimal, well-tested, and directly solves the reported crash issue without introducing new risks. The manual test steps mentioned in the test plan (running REFRESH CATALOG FULL and verifying SHOW CONTRACT MESSAGES) should be performed by the maintainer before merging, but the automated test coverage gives confidence in the fix. Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
ako
left a comment
There was a problem hiding this comment.
Code Review
Fix is correct and well-scoped. One-line change with a clear, reproducible crash behind it.
What the fix does
The synthetic for a row is a SHA-256 of svcQN + "|channel|" + ch.Name + "|" + ch.MessageRef. When Mendix Portal's AsyncAPI document repeats the same channel+messageRef combination, the same hash is generated twice, hitting the Id TEXT PRIMARY KEY constraint. INSERT OR IGNORE is the right idiom here — duplicate IDs mean genuinely identical data (same hash inputs), so silently dropping the second row loses nothing.
Minor notes
Potential gap in sibling tables — contract_entities and contract_actions use plain INSERT INTO with the same SHA-256 synthetic-ID approach. A malformed $metadata document with duplicate entity or action names would hit the same crash. Low priority since OData documents tend to be well-formed, but worth a follow-up.
Missing bug-test script — per project checklist, bug fixes should include an mdl-examples/bug-tests/ MDL script that reproduces the symptom. The manual test plan with screenshots is a good substitute for Studio Pro validation, but a short mdl-examples/bug-tests/533-duplicate-contract-messages.mdl would let the regression be caught automatically in CI.
fix-issue.md not updated — the symptom (REFRESH CATALOG FULL crash → UNIQUE constraint on contract_messages) is not in .claude/skills/fix-issue.md. New contributors tracing a similar crash in the future won't find it in the map.
Verdict
The fix is safe and correct. The missing bug-test and fix-issue.md entry are process gaps rather than blockers — given that this crashed a production catalog build, landing the fix quickly is the right call.
ako
left a comment
There was a problem hiding this comment.
Code Review
Fix is correct and well-scoped. One-line change with a clear, reproducible crash behind it.
What the fix does
The synthetic Id for a contract_messages row is a SHA-256 of svcQN + "|channel|" + ch.Name + "|" + ch.MessageRef. When Mendix Portal's AsyncAPI document repeats the same channel+messageRef combination, the same hash is generated twice, hitting the Id TEXT PRIMARY KEY constraint. INSERT OR IGNORE is the right idiom here — duplicate IDs mean genuinely identical data (same hash inputs), so silently dropping the second row loses nothing.
Minor notes
Potential gap in sibling tables — contract_entities and contract_actions use plain INSERT INTO with the same SHA-256 synthetic-ID approach. A malformed $metadata document with duplicate entity or action names would hit the same crash. Low priority since OData documents tend to be well-formed, but worth a follow-up.
Missing bug-test script — per project checklist, bug fixes should include an mdl-examples/bug-tests/ MDL script that reproduces the symptom. The manual test plan with screenshots is a good substitute for Studio Pro validation, but a short mdl-examples/bug-tests/533-duplicate-contract-messages.mdl would let the regression be caught automatically in CI.
fix-issue.md not updated — the symptom (REFRESH CATALOG FULL crash → UNIQUE constraint on contract_messages) is not in .claude/skills/fix-issue.md. New contributors tracing a similar crash in the future won't find it in the map.
Verdict
The fix is safe and correct. The missing bug-test and fix-issue.md entry are process gaps rather than blockers — given that this crashed a production catalog build, landing the fix quickly is the right call.
Summary
INSERT OR IGNORE INTO contract_messagesto tolerate duplicate rows from Mendix Portal's AsyncAPI documentsProblem
Mendix-portal's business event module has duplicate channel references across services. This caused a UNIQUE constraint violation that crashed the entire catalog build, making
REFRESH CATALOG FULLfail — which blocks all cross-reference queries (callers, callees, impact analysis).Test plan
go build ./mdl/catalog/passesgo test ./mdl/catalog/passes (190 tests)REFRESH CATALOG FULLagainst a Mendix Portal MPR to confirm no crashSHOW CONTRACT MESSAGESreturns expected rows