Skip to content

feat(invalidation): replace Postgres LISTEN/NOTIFY with GCP Pub/Sub#211

Open
steventohme wants to merge 2 commits into
mainfrom
steven/feat/pubsub-invalidation
Open

feat(invalidation): replace Postgres LISTEN/NOTIFY with GCP Pub/Sub#211
steventohme wants to merge 2 commits into
mainfrom
steven/feat/pubsub-invalidation

Conversation

@steventohme
Copy link
Copy Markdown
Collaborator

Summary

  • Removes the long-lived Postgres connection held per replica for cache invalidation (LISTEN router_installation_invalidate) — showed up as long-running transactions and burned connection pool slots unnecessarily
  • Adds internal/pubsub/invalidation.go with InvalidationNotifier (publishes installationID) and InvalidationListener (subscribes via Receive) backed by cloud.google.com/go/pubsub/v2
  • Deletes internal/postgres/invalidation.go (PgxInvalidationNotifier + InvalidationListener using WaitForNotification)
  • Wires up in main.go from three new required env vars: PUBSUB_PROJECT_ID, PUBSUB_TOPIC_ROUTER_INVALIDATION, PUBSUB_SUBSCRIPTION_ROUTER_INVALIDATION
  • The 5-min cache TTL remains as the safety net for missed invalidations

New env vars required

Var Example
PUBSUB_PROJECT_ID workweave-prod-01
PUBSUB_TOPIC_ROUTER_INVALIDATION router-installation-invalidate
PUBSUB_SUBSCRIPTION_ROUTER_INVALIDATION router-installation-invalidate-sub

For local dev / selfhosted: set PUBSUB_EMULATOR_HOST=localhost:8085 to route to the Pub/Sub emulator (same as Weave's distr/pubsub-emulator setup).

Test plan

  • Deploy to staging with new env vars set, verify router boots and logs "Invalidation listener active"
  • Rotate an installation key, confirm cache invalidation propagates without waiting for TTL
  • Confirm no long-running idle Postgres sessions from the router after deploy

🤖 Generated with Claude Code

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 44cc1af. Configure here.

Comment thread cmd/router/main.go Outdated
Comment thread cmd/router/main.go Outdated
Removes the long-lived Postgres connection held per replica for cache
invalidation (LISTEN router_installation_invalidate) and replaces it
with GCP Pub/Sub.

- Delete internal/postgres/invalidation.go (PgxInvalidationNotifier,
  InvalidationListener using WaitForNotification)
- Add internal/pubsub/invalidation.go with InvalidationNotifier
  (publishes installationID to a Pub/Sub topic) and
  InvalidationListener (subscribes via Receive)
- Wire up in main.go from three new env vars:
    PUBSUB_PROJECT_ID
    PUBSUB_TOPIC_ROUTER_INVALIDATION
    PUBSUB_SUBSCRIPTION_ROUTER_INVALIDATION
- Add cloud.google.com/go/pubsub/v2 dependency

The Postgres LISTEN approach held one persistent idle connection per
replica, showing up as long-running transactions and burning connection
pool slots unnecessarily. The 5-min cache TTL remains as the safety net
for missed invalidations.
@steventohme steventohme force-pushed the steven/feat/pubsub-invalidation branch from 44cc1af to 5b73c1b Compare May 21, 2026 00:07
- Each replica creates its own subscription (<prefix>-<uuid>) via
  SubscriptionAdminClient at boot and deletes it on shutdown. The env
  var PUBSUB_SUBSCRIPTION_ROUTER_INVALIDATION is now a prefix. A shared
  subscription would load-balance, defeating cross-fleet broadcast.
- Set ExpirationPolicy (24h TTL) so subscriptions leaked by crashed
  replicas are reclaimed automatically.
- Add InvalidationNotifier.Stop() and defer it in main so pending
  publishes are flushed and background goroutines clean up on shutdown.

Addresses Cursor Bugbot review on #211.
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