diff --git a/server/server.go b/server/server.go index db6ddc71..e688d147 100644 --- a/server/server.go +++ b/server/server.go @@ -481,12 +481,14 @@ func (s *Server) stop() { } func (s *Server) closeDatabases() { - if s.userManager != nil { - s.userManager.Close() - } + // Message cache first: it may still be writing its last batch, and on Postgres all stores + // share one pool, so closing any other store first would close the pool under that write if s.messageCache != nil { s.messageCache.Close() } + if s.userManager != nil { + s.userManager.Close() + } if s.webPush != nil { s.webPush.Close() } diff --git a/server/server_test.go b/server/server_test.go index e144a1cc..e92484f4 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -26,6 +26,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/stretchr/testify/require" "golang.org/x/crypto/bcrypt" + "heckel.io/ntfy/v2/db/pg" dbtest "heckel.io/ntfy/v2/db/test" "heckel.io/ntfy/v2/log" "heckel.io/ntfy/v2/message" @@ -5476,3 +5477,23 @@ func TestServer_StopFlushesBatchedMessages(t *testing.T) { require.Nil(t, err) require.Equal(t, 2, len(messages)) } + +func TestServer_StopFlushesBatchedMessages_Postgres(t *testing.T) { + // Same as TestServer_StopFlushesBatchedMessages on Postgres, where all stores share one + // pool: closing another store first used to close the pool under the pending batch write + schemaDSN := dbtest.CreateTestPostgresSchema(t) + conf := newTestConfig(t, schemaDSN) + conf.CacheBatchSize = 100 + conf.CacheBatchTimeout = time.Hour + s := newTestServer(t, conf) + require.Equal(t, 200, request(t, s, "PUT", "/mytopic", "batched 1", nil).Code) + require.Equal(t, 200, request(t, s, "PUT", "/mytopic", "batched 2", nil).Code) + s.Stop() + + host, err := pg.Open(schemaDSN) + require.Nil(t, err) + defer host.DB.Close() + var count int + require.Nil(t, host.DB.QueryRow(`SELECT COUNT(*) FROM message WHERE topic = 'mytopic'`).Scan(&count)) + require.Equal(t, 2, count) +}