Repository navigation
fix(api-server): stop oidc/route jsonb normalization bumping gateway generation - #384
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Central YAML (inherited) Review profile: CHILL Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Amber reviewStatus: Complete |
…ate changes oidc and route are jsonb columns, so PostgreSQL returns normalized text (key order, spacing) that never byte-equals the compact JSON the control plane writes back. desiredStateChanged reported a spec change on every UpdateGateway, bumping generation and clearing provisioning conditions, which re-opened the control plane's convergence gate. Gateways flapped between Running and Provisioning as they were re-provisioned every ~7s. Compare the two fields semantically. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
45451d9 to
f2e01b1
Compare
There was a problem hiding this comment.
Verdict
This remains a tight, correct fix. oidc/route are jsonb columns, so the PostgreSQL-normalized text (key order, spacing) never byte-equals the compact JSON the control plane writes back; the old strEq compare therefore bumped generation on every UpdateGateway, re-opening the convergence gate and flapping gateways between Running and Provisioning. Comparing those two fields semantically with jsonEq (nil-safe, byte fast-path, reflect.DeepEqual on the unmarshaled documents) resolves the spurious churn while leaving every other desired-state field on the strict strEq compare.
Findings
No new findings. The rebased head is diff-identical to the previously reviewed change: jsonEq is nil-safe (service.go:250-262), preserves the desired-state/observed-state split documented in data-model.spec.md (service.go:225-242), adds no secrets to logs, and weakens no pre-existing test assertion. The net-new desired_state_test.go is additive and covers the normalization no-op, a real audience change, and the cleared-field transition.
Cross-PR coordination
No material cross-PR coordination issue requires maintainer action.
Previous concerns
- Minor -
jsonEqdoc comment mischaracterized the non-JSON path as a string compare: Addressed. The comment atservice.go:249now reads "Unparseable values are treated as changed unless byte-identical," which matches the actual behavior: after the*a == *bfast path, ajson.Unmarshalfailure on either value returnsfalse(service.go:254-260).
The committer addressed the previous concerns.
Findings Summary (ordered by severity, highest first):
No outstanding findings.
Convention Checklist
| Convention | Result |
|---|---|
No panic() in production code |
Pass |
Errors wrapped with fmt.Errorf context |
Pass |
| No secrets in logs or responses | Pass |
| Input validated | Pass |
| Test assertions not silently weakened | Pass |
| Conventional commit message | Pass |
7e449fd

Problem
Existing gateways toggled between Running and Provisioning. The control plane wrote back
oidcon every reconcile as compact JSON; theoidc/routejsonb columns return normalized text, sodesiredStateChanged(raw string compare) saw a spec change every time. That bumpedgenerationpastobserved_generation, defeating the convergence gate, so each gateway was fully re-provisioned about every 7s (phase set to Provisioning, then promoted by the health reconciler).This was introduced by #151
Fix
Compare
oidcandroutesemantically (jsonEq), falling back to a string compare for non-JSON values.Testing
TestDesiredStateChangedIgnoresJSONNormalizationmake lintand api-servermake testpass locally🤖 Generated with Claude Code