Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
59 lines
2.2 KiB
Markdown
59 lines
2.2 KiB
Markdown
# 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:
|
||
|
||
1. `upsertEmailProvider → finalizeGoogleProvider`
|
||
2. `finalizeGoogleProvider → GmailWebhookService.setupGmailWebhook`
|
||
3. `updateEmailProvider → finalizeGoogleProvider` (when the user hit **Save**)
|
||
4. Same nested path as #2
|
||
|
||
Google interpreted this as spammy topic/subscription creation and suspended the push subscription.
|
||
|
||
## Target Design
|
||
|
||
```mermaid
|
||
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:
|
||
|
||
* **`configureGmailProvider`** is the *only* function that may call `setupPubSub`.
|
||
* Provider CRUD operations set `skipAutomation=true`, so normal **Save** does *not* touch Pub/Sub.
|
||
* A timestamp `pubsub_initialised_at` in `google_email_provider_config` guards against accidental extra runs (24-hour cool-down) unless `force=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:
|
||
|
||
```http
|
||
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).
|