From 2128f21e81435fd2aa7076e5d7d5eea6fc61bc3a Mon Sep 17 00:00:00 2001 From: steve-chavez Date: Tue, 12 Mar 2024 18:41:36 -0500 Subject: [PATCH] fix: upgrade hasql-notifications to show error --- CHANGELOG.md | 2 +- nix/overlays/haskell-packages.nix | 16 ++++++++++++++-- src/PostgREST/AppState.hs | 4 ++-- src/PostgREST/Observation.hs | 16 ++++++++-------- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index befde5406e..51de9304cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - #3224, Return status code 406 for non-accepted media type instead of code 415 - @wolfgangwalther - #3160, Fix using select= query parameter for custom media type handlers - @wolfgangwalther - #3237, Dump media handlers and timezones with --dump-schema - @wolfgangwalther - - #3323, Don't hide error on LISTEN channel failure - @steve-chavez + - #3323, #3324, Don't hide error on LISTEN channel failure - @steve-chavez ### Deprecated diff --git a/nix/overlays/haskell-packages.nix b/nix/overlays/haskell-packages.nix index 16a25bf0fa..f1b68545db 100644 --- a/nix/overlays/haskell-packages.nix +++ b/nix/overlays/haskell-packages.nix @@ -19,15 +19,18 @@ let # # To temporarily pin unreleased versions from GitHub: # = - # prev.callCabal2nixWithOptions "" (super.fetchFromGitHub { + # lib.dontCheck (prev.callCabal2nixWithOptions "" (super.fetchFromGitHub { # owner = ""; # repo = ""; # rev = ""; # sha256 = ""; - # }) "--subpath=" {}; + # }) "--subpath=." {}); # # To fill in the sha256: # update-nix-fetchgit nix/overlays/haskell-packages.nix + # + # Nowadays you can just delete the sha256 attribute above and nix will assume a fake sha. + # Once you build the derivation it will suggest the correct sha. configurator-pg = prev.callHackageDirect @@ -48,6 +51,15 @@ let hasql-pool = lib.dontCheck prev.hasql-pool_0_10; + hasql-notifications = lib.dontCheck (prev.callHackageDirect + { + pkg = "hasql-notifications"; + ver = "0.2.1.0"; + sha256 = "sha256-MEIirDKR81KpiBOnWJbVInWevL6Kdb/XD1Qtd8e6KsQ="; + } + { } + ); + }; in { diff --git a/src/PostgREST/AppState.hs b/src/PostgREST/AppState.hs index 2032c7dddd..4fd6d3a781 100644 --- a/src/PostgREST/AppState.hs +++ b/src/PostgREST/AppState.hs @@ -492,11 +492,11 @@ listener appState observer = do exitFailure where handleFinally dbChannel False err = do - observer $ DBListenerFailNoRecoverObs dbChannel err + observer $ DBListenerFailRecoverObs False dbChannel err killThread (getMainThreadId appState) handleFinally dbChannel True err = do -- if the thread dies, we try to recover - observer $ DBListenerFailRecoverObs dbChannel err + observer $ DBListenerFailRecoverObs True dbChannel err putIsListenerOn appState False -- assume the pool connection was also lost, call the connection worker connectionWorker appState diff --git a/src/PostgREST/Observation.hs b/src/PostgREST/Observation.hs index 679e33eb09..98370ef98d 100644 --- a/src/PostgREST/Observation.hs +++ b/src/PostgREST/Observation.hs @@ -9,6 +9,7 @@ module PostgREST.Observation ) where import qualified Data.ByteString.Lazy as LBS +import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Hasql.Connection as SQL import qualified Hasql.Pool as SQL @@ -38,8 +39,7 @@ data Observation | ConnectionPgVersionErrorObs SQL.UsageError | DBListenerStart Text | DBListenerFail Text SQL.ConnectionError - | DBListenerFailNoRecoverObs Text (Either SomeException ()) - | DBListenerFailRecoverObs Text (Either SomeException ()) + | DBListenerFailRecoverObs Bool Text (Either SomeException ()) | ConfigReadErrorObs | ConfigReadErrorFatalObs SQL.UsageError Text | ConfigReadErrorNotFatalObs SQL.UsageError @@ -85,10 +85,8 @@ observationMessage = \case "Listening for notifications on the " <> channel <> " channel" DBListenerFail channel err -> do "Could not listen for notifications on the " <> channel <> " channel. " <> show err - DBListenerFailNoRecoverObs channel err -> - showListenerError err <> ". Automatic recovery disabled on the " <> channel <> " channel" - DBListenerFailRecoverObs channel err -> - showListenerError err <> ". Retrying listening for notifications on the " <> channel <> " channel.." + DBListenerFailRecoverObs recover channel err -> + "Could not listen for notifications on the " <> channel <> " channel. " <> showListenerError err <> (if recover then " Retrying listening for notifications.." else mempty) ConfigReadErrorObs -> "An error ocurred when trying to query database settings for the config parameters" ConfigReadErrorFatalObs usageErr hint -> @@ -112,5 +110,7 @@ observationMessage = \case jsonMessage err = T.decodeUtf8 . LBS.toStrict . Error.errorPayload $ Error.PgError False err showListenerError :: Either SomeException () -> Text - showListenerError (Left e) = show e - showListenerError (Right _) = "Failed getting notifications" -- this should not happen as the listener will never finish with a Right result + showListenerError (Right _) = "Failed getting notifications" -- should not happen as the listener will never finish (hasql-notifications uses `forever` internally) with a Right result + showListenerError (Left e) = + let showOnSingleLine txt = T.intercalate " " $ T.filter (/= '\t') <$> T.lines txt in -- the errors from hasql-notifications come intercalated with "\t\n" + showOnSingleLine $ show e