Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
2.2 KiB
Pub/Sub Architecture – Single-Initialisation Design
Last updated: 2025-07-19
This document explains the single-run Google Pub/Sub initialisation strategy that replaced the previous logic where the same topic/subscription could be created up to four times during a single Gmail OAuth flow. The refactor prevents Google from disabling subscriptions due to excessive creation attempts and clarifies the separation of concerns in the codebase.
Problem Recap
Previously the stack called setupPubSub four times:
upsertEmailProvider → finalizeGoogleProviderfinalizeGoogleProvider → GmailWebhookService.setupGmailWebhookupdateEmailProvider → finalizeGoogleProvider(when the user hit Save)- Same nested path as #2
Google interpreted this as spammy topic/subscription creation and suspended the push subscription.
Target Design
sequenceDiagram
participant OAuth as OAuth Callback
participant CFG as configureGmailProvider
participant PubSub as setupPubSub
participant Gmail as GmailWebhookService.registerWatch
OAuth->>CFG: providerId, tenant, projectId
CFG->>PubSub: create-or-update topic+sub (once)
PubSub-->>CFG: OK
CFG->>Gmail: register watch (no Pub/Sub)
Gmail-->>CFG: historyId, expiration
Key points:
configureGmailProvideris the only function that may callsetupPubSub.- Provider CRUD operations set
skipAutomation=true, so normal Save does not touch Pub/Sub. - A timestamp
pubsub_initialised_atingoogle_email_provider_configguards against accidental extra runs (24-hour cool-down) unlessforce=true.
Code Pointers
- Orchestration:
server/src/lib/actions/email-actions/configureGmailProvider.ts - Gmail watch only:
server/src/services/email/GmailWebhookService.ts - Low-level GCP client:
server/src/lib/actions/email-actions/setupPubSub.ts
Refresh Endpoint
Admins can explicitly refresh the topic/subscription:
POST /api/email/refresh-watch
Internally this calls configureGmailProvider({ force: true }) and therefore bypasses the 24-hour guard.
Migration Notes
Details of the implementation phases, testing matrix and roll-out strategy are preserved in the original engineering plan (git history of this file).