Skip to content

Read-only scope lists, 503 on statement timeouts, log read-model restores - #264

Merged
MrAlders0n merged 1 commit into
devfrom
fix/soak-followups
Oct 21, 2026
Merged

MrAlders0n merged 1 commit into
devfrom
fix/soak-followups

Conversation

@MrAlders0n

Copy link
Copy Markdown
Member

Three small fixes found during the dev-box soak of the 2.1 release candidate. No SQL, migration or result changes.

Read-only servers: region scope lists were empty

server.read_only: true skipped meshmapper.New, which only reads the saved scope catalogues and fills the in-memory scope store. Region handlers filter scope names through that store, so /scopes?region= and /stats/scopes?region= returned [] (found in the dev-data timing run: region=golm gave [] where a writer gives 14 scopes). The restore now runs in both modes; the meshmapper.scopes refresh task (writes, HTTP) stays writer-only. A read-only server's lists reflect the writer's catalogues as of its boot.

TestReadOnlyBootWritesNothingPostgres now seeds a saved SEA catalogue after the control boot and checks the read-only boot lists its scope for region pnw, while still proving no table changed. With the old gate it fails with 200 [].

Statement timeouts answer 503, not 500

The API pools stop statements at 35 s (120 s on api_slow). A statement that hit the limit returned a bare 500; 2.0.7's pool had no limit, so those pages answered slowly instead. On the dev box a cold /routes/{iata}/{pathKey}/observations (7-day window) hit it. respondUnavailable now maps SQLSTATE 57014 and context.DeadlineExceeded (not context.Canceled) to 503, code deadline_exceeded, Retry-After: 10. It applies to route evidence and the four read-model pages; beacon_api_unavailable_total gains reason="timeout". Other handlers still answer 500 on a timeout.

Read-model trust logs restores

A drop logged one WARN and the restore logged nothing, so a log reader couldn't tell when region pages came back (seen in the soak's Postgres restart test). Trust.update now logs read model trusted again: its pages are served from it on each restore after the first trust, and ObserveRun logs read model untrusted: repair runs fixed rows the writers missed once when the drop policy trips (that drop was silent too).

Checks

go build, go vet, gofmt, go test ./... with BEACON_TEST_POSTGRES_DSN (Postgres 16), go test -race ./internal/meshmapper ./internal/scopestore, govulncheck (0 affecting), swagger regenerated, plan policy unchanged.

Docs: MeshCore-Beacon/beacon-docs (contract 503 row, read-only mode, trust log lines, metric reason).

Prod steps

None.

…ores

Read-only servers now restore the saved MeshMapper scope catalogues (a read-only
step), so region scope lists are no longer empty. A statement that hits the
pool's statement_timeout answers 503 with Retry-After on route evidence and the
read-model pages instead of 500. Read-model trust logs when it comes back after
a drop, and when repair runs drop it.
@MrAlders0n
MrAlders0n merged commit 0801411 into dev Oct 21, 2026
3 checks passed
@MrAlders0n
MrAlders0n deleted the fix/soak-followups branch October 21, 2026 15:28
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.

1 participant