fix(whatsmeow): reuse shared sqlstore.Container for PostgresAuthDB - #206
meguisouza wants to merge 1 commit into
Conversation
StartClient called sqlstore.New on every instance start, opening a new *sql.DB and re-running Upgrade against PostgresAuthDB. A few parallel QR/reconnects saturated PgBouncer (75 = 60+15) with bad connection. Reuse the pooled authDB from initPostgresAuthDB via NewWithDB + Upgrade once (sync.Once on a heap-allocated sharedSQLStore so value-receiver StartClient is safe). Users/GORM DB stays separate. Do not Close the shared container on disconnect — main owns authDB.
Reviewer's GuideThe PR changes WhatsApp auth-store initialization from per-StartClient sqlstore creation to a process-wide, sync.Once-managed container. PostgreSQL now reuses the existing pooled authDB and upgrades once, while SQLite receives a single similarly bounded pool; instance disconnects no longer need to close the shared store, whose lifecycle remains process-owned. Sequence diagram for shared WhatsApp auth-store initializationsequenceDiagram
participant Caller
participant Service as whatsmeowService
participant Store as sharedSQLStore
participant AuthDB as authDB
participant Container as sqlstore.Container
Caller->>Service: StartClient(cd)
Service->>Store: getSharedSQLStoreContainer()
Store->>Store: sync.Once.Do
alt PostgresAuthDB configured
Store->>AuthDB: NewWithDB(authDB, postgres, dbLog)
Store->>Container: Upgrade(ctx)
Container-->>Store: success
else SQLite fallback
Store->>Store: sql.Open(sqlite, dsn)
Store->>Container: NewWithDB(db, sqlite, dbLog)
Store->>Container: Upgrade(ctx)
Container-->>Store: success
end
Store-->>Service: shared container
Service-->>Caller: StartClient continues
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've reviewed your changes and they look great!
Sourcery assessment
Needs a human reviewer. A single shared container and one-time database upgrade now govern all WhatsApp auth sessions, so an initialization or connection-handling defect could prevent every client from connecting or leave persisted auth state needing repair. Reverting stops future use of the shared path, but it does not undo database writes already made.
Problem
When using PostgreSQL for the WhatsApp auth store (
POSTGRES_AUTH_DB), every call toStartClientopens a newsqlstoreviasqlstore.New(postgres, DSN). That path always runs whatsmeow/dbutilUpgrade(including the version-table check that surfaces asfailed to check if version table is up to date/failed to upgrade database).In production behind PgBouncer we saw:
cl_activeequal todefault_pool_size + reserve_pool_size, e.g. 60+15=75), with clients waiting close toquery_wait_timeout.Failed to create container: failed to upgrade database: … driver: bad connection./instance/qrand connect paths stall (e.g. QR returning 400 after ~5s) while the auth pool is saturated.container.Close()on the previous store, so eachStartClientcan leave another*sql.DBbehind. The process already opens a pooledauthDBininitPostgresAuthDB(SetMaxOpenConns/ idle / lifetime), butStartClientnever reuses it.This matches an older incident with the same stuck auth-DB connections at the pool ceiling. PgBouncer only makes the ceiling visible.
Fix
sqlstore.Container(sharedSQLStore+sync.Once, safe with value-receiverStartClient).sqlstore.NewWithDB(authDB, "postgres", …)+Upgradeonce, reusinginitPostgresAuthDB.mainownsauthDB.Close().How to reproduce
POSTGRES_AUTH_DBvia PgBouncer with a modestdefault_pool_size.SHOW POOLS+ logs forFailed to create container/bad connection.Test plan
POSTGRES_AUTH_DB.authDBpool limits.StartClientdoes notsql.Opennew auth pools.Happy to adjust structure if preferred.
Summary by Sourcery
Reuse one upgraded authentication SQL store across client starts to stabilize reconnects and avoid accumulating database pools.
Bug Fixes:
Enhancements: