Client Manager

The Client Manager is a subsystem responsible for the lifecycle management of device (client) data across multi-tenant PostgreSQL schemas. It consists of multiple independent sub-workers, each handling a specific aspect of device data management.

Multi-Tenant Architecture

Each customer’s device data is stored in an isolated PostgreSQL schema named tenant_<customerId>. The TenantSchemaManager class handles schema creation, migration, and deletion.

Sub-Workers

Writer

  • Subscription: client-manager.writer

  • Processes device registration and update events from Pub/Sub

  • Writes device data to the appropriate tenant schema in PostgreSQL

  • On transient failure, publishes the message to the Republisher for retry

  • On permanent failure, publishes to client-manager.writer-errors

Republisher

  • Subscription: client-manager.republisher

  • Retry mechanism for failed Writer messages

  • Maximum retry count: 5

  • After exhausting retries, publishes to client-manager.writer-errors

Push Token Status Updater

  • Subscription: client-manager.push-token-status (push) and client-manager.web-push-token-status (web push)

  • Updates push token validity status in PostgreSQL

  • Supports consuming from both push and web push subscriptions simultaneously via -t both flag

  • Processes messages in batches (batch size: 100, interval: 1000ms)

Tenant Activator

  • Subscription: client-manager.activate-customer

  • Creates and initializes tenant schemas when new customers are activated

  • Uses TenantSchemaManager to create the schema and run tenant migrations

Account Deletion

  • Subscription: client-manager.account-deletion

  • Processes full account/customer deletion events

  • Drops the entire tenant schema for the customer

  • Uses AuditLogger for compliance tracking

Contact Deletion Worker

  • Subscription: client-manager.contact-deletion

  • Processes individual contact deletion messages

  • Deletes device records for specific contacts from PostgreSQL

  • Errors published to client-manager.contact-deletion-errors

Contact Deletion Job (Batch)

  • Scheduled batch job (no Pub/Sub subscription)

  • Queries BigQuery for contacts deleted across all active customers

  • Publishes deletion messages to client-manager.contact-deletion topic for processing by the Contact Deletion Worker

  • Page size: 1M contacts per query

Orphan Deletion (Batch)

  • Scheduled batch job (no Pub/Sub subscription)

  • Deletes orphaned devices — devices with no associated contact that are older than a configurable threshold (default: 30 days)

  • Includes retry logic for failed customers

  • Supports a configurable customer exclusion list

Dashboard Collector (Batch)

  • Scheduled batch job (no Pub/Sub subscription)

  • Collects per-tenant metrics (device counts, sync validation, etc.)

  • Creates missing tenant schemas if needed

  • Writes results to dashboard_tenant_metrics and dashboard_tenant_metrics_history tables

  • For dashboard queries and views, see Client Manager Dashboard

Sequence Diagrams

Device Write with Retry

Shows the Writer and Republisher retry loop when writing device data fails transiently.

sequenceDiagram participant PS as Pub/Sub
client-manager.writer participant W as Writer participant PG as PostgreSQL
tenant_ participant RP as Pub/Sub
client-manager.republisher participant R as Republisher participant ERR as Pub/Sub
client-manager.writer-errors PS->>W: device registration event W->>PG: write device data alt success PG-->>W: OK W-->>PS: ack else transient error PG-->>W: error W->>RP: publish (retryCount=1) W-->>PS: ack RP->>R: deliver message R->>PG: retry write alt success PG-->>R: OK R-->>RP: ack else still failing (retryCount < 5) PG-->>R: error R->>RP: publish (retryCount++) R-->>RP: ack Note over R,RP: loop until success
or retryCount = 5 else retries exhausted (retryCount = 5) PG-->>R: error R->>ERR: publish to writer-errors R-->>RP: ack end else permanent error PG-->>W: error W->>ERR: publish to writer-errors W-->>PS: ack end

Contact Deletion Flow

Shows how the batch deletion job discovers deleted contacts and fans out to individual deletion workers.

sequenceDiagram participant JOB as Contact Deletion Job
(scheduled batch) participant BQ as BigQuery participant PS as Pub/Sub
client-manager.contact-deletion participant CDW as Contact Deletion Worker participant PG as PostgreSQL
tenant_ participant ERR as Pub/Sub
contact-deletion-errors JOB->>BQ: query deleted contacts
(all active customers) BQ-->>JOB: pages of deleted contacts (up to 1M per page) loop for each deleted contact JOB->>PS: publish deletion message
(customerId, contactId) end PS->>CDW: deliver deletion message CDW->>PG: DELETE devices
WHERE contact = contactId alt success PG-->>CDW: OK CDW-->>PS: ack else error PG-->>CDW: error CDW->>ERR: publish to contact-deletion-errors CDW-->>PS: ack end

Tenant Lifecycle

Shows tenant activation and account deletion as complementary operations.

sequenceDiagram participant ACT as Pub/Sub
activate-customer participant TA as Tenant Activator participant PG as PostgreSQL participant AD as Account Deletion participant DEL as Pub/Sub
account-deletion participant AUDIT as AuditLogger Note over ACT,PG: Tenant Activation ACT->>TA: new customer event TA->>PG: CREATE SCHEMA tenant_ TA->>PG: run tenant migrations PG-->>TA: schema ready TA-->>ACT: ack Note over DEL,AUDIT: Account Deletion DEL->>AD: account deletion event AD->>AUDIT: log deletion (compliance) AD->>PG: DROP SCHEMA tenant_ PG-->>AD: schema dropped AD-->>DEL: ack

Dependencies

  • PostgreSQL: Primary storage for all device data, organized in tenant schemas

  • BigQuery: Source for contact deletion data

  • Redis: Used for caching and coordination

  • Pub/Sub: Message transport for all event-driven sub-workers