Skip to content

Use PostgreSQL unlogged tables + LISTEN/NOTIFY for multi-worker support#2

Open
cmorg789 wants to merge 1 commit intomasterfrom
claude/postgres-unlogged-pooling-7gBkY
Open

Use PostgreSQL unlogged tables + LISTEN/NOTIFY for multi-worker support#2
cmorg789 wants to merge 1 commit intomasterfrom
claude/postgres-unlogged-pooling-7gBkY

Conversation

@cmorg789
Copy link
Owner

@cmorg789 cmorg789 commented Mar 3, 2026

Moves the three in-memory state systems (rate limiter, presence, gateway event fan-out) that previously forced --workers 1 into shared PostgreSQL unlogged tables with cross-worker notification via LISTEN/NOTIFY.

Key changes:

  • New src/vox/db/shared_state.py: creates unlogged _rate_buckets, _presence, and _connections tables; runs a background LISTEN loop for cross-worker event dispatch; falls back to in-memory dicts on SQLite for dev compatibility.
  • Rate limiter: check() is now async, delegates to shared_state for atomic token-bucket operations in PostgreSQL.
  • Gateway hub: local connections dict stays (WebSockets are process- local), but broadcast() publishes via NOTIFY so other workers deliver events to their own clients. Presence reads/writes go through shared tables.
  • Snowflake IDs: layout changed to 42-bit ts | 10-bit worker | 12-bit seq so each worker generates collision-free IDs.
  • Deployment docs updated: --workers 4 default when on PostgreSQL.

https://claude.ai/code/session_0113vE6YvpWbp1zCdABBH1r7

Moves the three in-memory state systems (rate limiter, presence, gateway
event fan-out) that previously forced --workers 1 into shared PostgreSQL
unlogged tables with cross-worker notification via LISTEN/NOTIFY.

Key changes:
- New src/vox/db/shared_state.py: creates unlogged _rate_buckets,
  _presence, and _connections tables; runs a background LISTEN loop
  for cross-worker event dispatch; falls back to in-memory dicts on
  SQLite for dev compatibility.
- Rate limiter: check() is now async, delegates to shared_state for
  atomic token-bucket operations in PostgreSQL.
- Gateway hub: local connections dict stays (WebSockets are process-
  local), but broadcast() publishes via NOTIFY so other workers
  deliver events to their own clients. Presence reads/writes go
  through shared tables.
- Snowflake IDs: layout changed to 42-bit ts | 10-bit worker | 12-bit
  seq so each worker generates collision-free IDs.
- Deployment docs updated: --workers 4 default when on PostgreSQL.

https://claude.ai/code/session_0113vE6YvpWbp1zCdABBH1r7
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.

2 participants