add(logs): Include a HINT when the LISTEN channel breaks due to a Postgres bug

The HINT shows a SQL command that solves the issue.
This commit is contained in:
Laurence Isla
2026-04-03 16:36:55 -05:00
committed by Steve Chavez
parent aae929a718
commit 250747aadc
3 changed files with 15 additions and 1 deletions
+4
View File
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. From versio
## Unreleased ## Unreleased
### Added
- Log a `HINT` when the LISTEN channel stops working due to a PostgreSQL bug by @laurenceisla in #4581
## [14.7] - 2026-03-20 ## [14.7] - 2026-03-20
### Fixed ### Fixed
+4 -1
View File
@@ -10,7 +10,8 @@ import qualified Hasql.Connection as SQL
import qualified Hasql.Notifications as SQL import qualified Hasql.Notifications as SQL
import PostgREST.AppState (AppState, getConfig) import PostgREST.AppState (AppState, getConfig)
import PostgREST.Config (AppConfig (..)) import PostgREST.Config (AppConfig (..))
import PostgREST.Observation (Observation (..)) import PostgREST.Observation (Observation (..),
isDbListenerBug)
import PostgREST.Version (prettyVersion) import PostgREST.Version (prettyVersion)
import qualified PostgREST.AppState as AppState import qualified PostgREST.AppState as AppState
@@ -36,6 +37,8 @@ retryingListen appState = do
onError err = do onError err = do
AppState.putIsListenerOn appState False AppState.putIsListenerOn appState False
observer $ DBListenFail dbChannel (Right err) observer $ DBListenFail dbChannel (Right err)
when (isDbListenerBug err) $
observer DBListenBugHint
unless configDbPoolAutomaticRecovery $ unless configDbPoolAutomaticRecovery $
killThread mainThreadId killThread mainThreadId
+7
View File
@@ -13,6 +13,7 @@ module PostgREST.Observation
, observationMessage , observationMessage
, ObservationHandler , ObservationHandler
, showOnSingleLine , showOnSingleLine
, isDbListenerBug
) where ) where
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
@@ -47,6 +48,7 @@ data Observation
| DBListenStart Text | DBListenStart Text
| DBListenFail Text (Either SQL.ConnectionError SomeException) | DBListenFail Text (Either SQL.ConnectionError SomeException)
| DBListenRetry Int | DBListenRetry Int
| DBListenBugHint -- https://github.com/PostgREST/postgrest/issues/3147
| DBListenerGotSCacheMsg ByteString | DBListenerGotSCacheMsg ByteString
| DBListenerGotConfigMsg ByteString | DBListenerGotConfigMsg ByteString
| DBListenerConnectionCleanupFail SomeException | DBListenerConnectionCleanupFail SomeException
@@ -119,6 +121,8 @@ observationMessage = \case
either showListenerConnError showListenerException listenErr either showListenerConnError showListenerException listenErr
DBListenRetry delay -> DBListenRetry delay ->
"Retrying listening for database notifications in " <> (show delay::Text) <> " seconds..." "Retrying listening for database notifications in " <> (show delay::Text) <> " seconds..."
DBListenBugHint ->
"HINT: This is likely a bug in the notification queue, try executing the following to solve it: select pg_notification_queue_usage();"
DBListenerGotSCacheMsg channel -> DBListenerGotSCacheMsg channel ->
"Received a schema cache reload message on the " <> show channel <> " channel" "Received a schema cache reload message on the " <> show channel <> " channel"
DBListenerGotConfigMsg channel -> DBListenerGotConfigMsg channel ->
@@ -181,3 +185,6 @@ observationMessage = \case
showOnSingleLine :: Char -> Text -> Text showOnSingleLine :: Char -> Text -> Text
showOnSingleLine split txt = T.intercalate " " $ T.filter (/= split) <$> T.lines txt -- the errors from hasql-notifications come intercalated with "\t\n" showOnSingleLine split txt = T.intercalate " " $ T.filter (/= split) <$> T.lines txt -- the errors from hasql-notifications come intercalated with "\t\n"
isDbListenerBug :: SomeException -> Bool
isDbListenerBug e = "could not access status of transaction" `T.isInfixOf` show e