From 8ade0d24560a097dd1a082fe4818e71bddcf1abb Mon Sep 17 00:00:00 2001 From: Felipe Medeiros Date: Fri, 14 Aug 2026 11:23:37 -0300 Subject: [PATCH 1/2] fix(whatsmeow): reusa o pool de conexoes existente no StartClient sqlstore.New() abria um *sql.DB novo, sem limites de pool e nunca fechado, toda vez que StartClient rodava (conexao inicial, reconexao manual, restart apos LoggedOut, loop de startup). Em producao isso vazou o max_connections do Postgres apos ~2 dias com poucas dezenas de instancias reconectando. Troca por sqlstore.NewWithDB(w.authDB, ...), reaproveitando o pool ja existente e limitado (SetMaxOpenConns/SetMaxIdleConns/etc, configurado em pkg/config/config.go). Como NewWithDB nao roda Upgrade sozinho como o New(), a chamada de Upgrade(ctx) foi movida para o call site. --- pkg/whatsmeow/service/whatsmeow.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/whatsmeow/service/whatsmeow.go b/pkg/whatsmeow/service/whatsmeow.go index 366f0edb..a78b62c3 100644 --- a/pkg/whatsmeow/service/whatsmeow.go +++ b/pkg/whatsmeow/service/whatsmeow.go @@ -319,14 +319,20 @@ func (w whatsmeowService) StartClient(cd *ClientData) { if w.config.WaDebug != "" { dbLog := waLog.Stdout("Database", w.config.WaDebug, true) if w.config.PostgresAuthDB != "" { - container, err = sqlstore.New(context.Background(), "postgres", w.config.PostgresAuthDB, dbLog) + // Reaproveita o pool já existente e limitado (w.authDB) em vez de abrir + // um *sql.DB novo e sem limites a cada StartClient — sqlstore.New() + // vazava um pool inteiro por chamada (nunca fechado), esgotando o + // max_connections do Postgres em produção. + container = sqlstore.NewWithDB(w.authDB, "postgres", dbLog) + err = container.Upgrade(context.Background()) } else { dsn := fmt.Sprintf("file:%s/dbdata/main.db?_pragma=foreign_keys(1)&_busy_timeout=5000&cache=shared&mode=rwc&_journal_mode=WAL", w.exPath) container, err = sqlstore.New(context.Background(), "sqlite", dsn, dbLog) } } else { if w.config.PostgresAuthDB != "" { - container, err = sqlstore.New(context.Background(), "postgres", w.config.PostgresAuthDB, nil) + container = sqlstore.NewWithDB(w.authDB, "postgres", nil) + err = container.Upgrade(context.Background()) } else { dsn := fmt.Sprintf("file:%s/dbdata/main.db?_pragma=foreign_keys(1)&_busy_timeout=5000&cache=shared&mode=rwc&_journal_mode=WAL", w.exPath) container, err = sqlstore.New(context.Background(), "sqlite", dsn, nil) From 33b6d186c27b05ece57abe76d9640318f647c7f9 Mon Sep 17 00:00:00 2001 From: Felipe Medeiros Date: Fri, 14 Aug 2026 12:19:33 -0300 Subject: [PATCH 2/2] address Sourcery review: guard nil authDB, shorten comment to English - Bail out early with a clear log if PostgresAuthDB is configured but authDB was never initialized, instead of letting NewWithDB receive a nil *sql.DB. - Shorten the explanatory comment above NewWithDB and switch it to English to match the rest of the codebase. --- pkg/whatsmeow/service/whatsmeow.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/whatsmeow/service/whatsmeow.go b/pkg/whatsmeow/service/whatsmeow.go index a78b62c3..d7fb0b07 100644 --- a/pkg/whatsmeow/service/whatsmeow.go +++ b/pkg/whatsmeow/service/whatsmeow.go @@ -316,13 +316,15 @@ func (w whatsmeowService) StartClient(cd *ClientData) { var container *sqlstore.Container + if w.config.PostgresAuthDB != "" && w.authDB == nil { + w.loggerWrapper.GetLogger(cd.Instance.Id).LogError("[%s] PostgresAuthDB is set but authDB was never initialized", cd.Instance.Id) + return + } + if w.config.WaDebug != "" { dbLog := waLog.Stdout("Database", w.config.WaDebug, true) if w.config.PostgresAuthDB != "" { - // Reaproveita o pool já existente e limitado (w.authDB) em vez de abrir - // um *sql.DB novo e sem limites a cada StartClient — sqlstore.New() - // vazava um pool inteiro por chamada (nunca fechado), esgotando o - // max_connections do Postgres em produção. + // Reuse the shared, pooled authDB instead of opening a new unbounded pool per call. container = sqlstore.NewWithDB(w.authDB, "postgres", dbLog) err = container.Upgrade(context.Background()) } else {