Changeset 0.32.0 (#206)
This commit is contained in:
65
CHANGELOG.md
65
CHANGELOG.md
@@ -1,5 +1,70 @@
|
||||
# Changelog
|
||||
|
||||
## [0.32.0] — 2026-03-19
|
||||
|
||||
### Summary
|
||||
|
||||
Multi-Replica HA: run 2+ backend replicas across nodes for node-level
|
||||
availability. All shared mutable state moves from in-process memory to
|
||||
Postgres — task scheduler uses `FOR UPDATE SKIP LOCKED` for atomic
|
||||
claim (no leader election), WebSocket tickets and rate limit counters
|
||||
become PG tables, and `SendToUser` is replaced by bus-routed
|
||||
`PublishToUser` for cross-pod event delivery. New `/healthz/ready`
|
||||
and `/healthz/live` probe endpoints. Helm defaults to 2 replicas with
|
||||
pod anti-affinity.
|
||||
|
||||
### New
|
||||
|
||||
- **`FOR UPDATE SKIP LOCKED` task scheduler** — every replica polls;
|
||||
PG serializes task handoff atomically. `ClaimDueTask` replaces
|
||||
`ListDue`. `CreateRunExclusive` conditional insert prevents
|
||||
double-execution. Startup jitter (0–15s) staggers replicas.
|
||||
- **PG ticket store** — `ws_tickets` table replaces in-memory
|
||||
`sync.Map`. Atomic `DELETE ... RETURNING` for single-use validation.
|
||||
30s TTL, reaper piggybacked on scheduler poll tick.
|
||||
- **PG rate limiter** — `rate_limit_counters` table with fixed-window
|
||||
`INSERT ON CONFLICT DO UPDATE`. Fail-open policy: DB errors allow
|
||||
the request rather than blocking auth. Cleanup piggybacked on
|
||||
scheduler poll tick.
|
||||
- **Cross-pod WebSocket delivery** — `Hub.PublishToUser` routes events
|
||||
through the bus → `pg_broadcast` → remote pod `publishLocal`.
|
||||
`TargetUserID` field on `Event` for targeted filtering.
|
||||
`tool.result.*` routing changed to `DirBoth` so browser tool results
|
||||
cross pods for `WaitFor`.
|
||||
- **Health probes** — `/healthz/ready` (PG ping, 2s timeout) and
|
||||
`/healthz/live` (process alive, no deps).
|
||||
- **Helm HA** — `backend.replicaCount: 2`, pod anti-affinity
|
||||
(`preferredDuringScheduling`, `kubernetes.io/hostname`), readiness
|
||||
and liveness probes pointed at new healthz endpoints.
|
||||
- **Schema `020_ha.sql`** — `ws_tickets` and `rate_limit_counters`
|
||||
tables (PG + SQLite).
|
||||
|
||||
### Changed
|
||||
|
||||
- **`SendToUser` → `PublishToUser`** — 18 call sites across 10 files
|
||||
migrated to bus-routed delivery for cross-pod reach.
|
||||
- **`ListDue` removed from `TaskStore`** — replaced by `ClaimDueTask`
|
||||
(atomic claim) + `CreateRunExclusive` (belt-and-suspenders guard).
|
||||
- **Rate limiter middleware** — rewritten to accept `store.RateLimitStore`
|
||||
instead of managing in-memory state. Constructor signature changed:
|
||||
`NewRateLimiter(store, rate, burst)`.
|
||||
- **`tool.result.*` routing** — `DirFromClient` → `DirBoth` to enable
|
||||
cross-pod `WaitFor`. WS subscriber explicitly filters `tool.result`
|
||||
to prevent re-sending to clients.
|
||||
|
||||
### Removed
|
||||
|
||||
- **`events/tickets.go`** — in-memory `TicketStore` replaced by
|
||||
`store.TicketStore` (PG/SQLite) + `TicketValidatorAdapter`.
|
||||
- **In-memory rate limiter** — visitor map and cleanup goroutine
|
||||
replaced by PG-backed store.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Team workflow route registration** — v0.31.2 team-scoped workflow
|
||||
CRUD routes (`/teams/:teamId/workflows`) were missing from `main.go`
|
||||
route registration. 12 routes added to `teamScoped` group.
|
||||
|
||||
## [0.31.2] — 2026-03-19
|
||||
|
||||
### Summary
|
||||
|
||||
Reference in New Issue
Block a user