fix: don't reload cache on every listener fail

Revert "prevent GSSAPI error between Listener and pool"

This reverts commit 4beac10d3d.
This commit is contained in:
steve-chavez
2024-06-25 20:03:22 -05:00
committed by Steve Chavez
parent 9d7e87b3e0
commit f912c0dd29
3 changed files with 6 additions and 33 deletions
+4
View File
@@ -9,6 +9,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #3558, Add the `admin-server-host` config to set the host for the admin server - @develop7
### Fixed
- #3147, Don't reload schema cache on every listener failure - @steve-chavez
### Changed
- #2052, Dropped support for PostgreSQL 9.6 - @wolfgangwalther
-27
View File
@@ -29,7 +29,6 @@ module PostgREST.AppState
, getObserver
, isLoaded
, isPending
, waitForListenerCanStart
) where
import qualified Data.Aeson as JSON
@@ -99,8 +98,6 @@ data AppState = AppState
, stateIsListenerOn :: IORef Bool
-- | starts the connection worker with a debounce
, debouncedConnectionWorker :: IO ()
-- | Binary semaphore used to sync the listener with the connectionWorker.
, stateListenerCanStart :: MVar ()
-- | Config that can change at runtime
, stateConf :: IORef AppConfig
-- | Time used for verifying JWT expiration
@@ -159,7 +156,6 @@ initWithPool (sock, adminSock) pool conf loggerState metricsState observer = do
<*> newIORef ConnPending
<*> newIORef False
<*> pure (pure ())
<*> newEmptyMVar
<*> newIORef conf
<*> mkAutoUpdate defaultUpdateSettings { updateAction = getCurrentTime }
<*> myThreadId
@@ -322,26 +318,6 @@ getNextListenerDelay = readIORef . stateNextListenerDelay
putNextListenerDelay :: AppState -> Int -> IO ()
putNextListenerDelay = atomicWriteIORef . stateNextListenerDelay
--------------------------------------------------------------------------------------
-------------------------------------------IMPORTANT----------------------------------
--------------------------------------------------------------------------------------
-- Both of these function ensure there's no parallel connection attempts between the listener and the connection pool.
-- Doing that raised an error with GSSAPI as discussed on https://github.com/PostgREST/postgrest/issues/3569.
-- Until the root cause is found and solved, we need to prevent parallel connection attempts.
-- tryPutMVar doesn't lock the thread. It should always succeed since
-- the connectionWorker is the only mvar producer.
setListenerCanStart :: AppState -> IO ()
setListenerCanStart appState = void $ tryPutMVar (stateListenerCanStart appState) ()
-- | As this IO action uses `takeMVar` internally, it will only return once
-- `stateListenerCanStart` has been set using `setListenerCanStart`.
waitForListenerCanStart :: AppState -> IO ()
waitForListenerCanStart = takeMVar . stateListenerCanStart
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
getConfig :: AppState -> IO AppConfig
getConfig = readIORef . stateConf
@@ -461,9 +437,6 @@ internalConnectionWorker appState@AppState{stateObserver=observer, stateMainThre
observer $ ExitUnsupportedPgVersion actualPgVersion minimumPgVersion
killThread mainThreadId
observer (DBConnectedObs $ pgvFullName actualPgVersion)
-- Wake up the Listener
when configDbChannelEnabled $
setListenerCanStart appState
-- this could be fail because the connection drops, but the loadSchemaCache will pick the error and retry again
-- We cannot retry after it fails immediately, because db-pre-config could have user errors. We just log the error and continue.
when configDbConfig $ reReadConfig False appState
+2 -6
View File
@@ -27,16 +27,10 @@ runListener appState = do
-- | Starts a LISTEN connection and handles notifications. It recovers with exponential backoff with a cap of 32 seconds, if the LISTEN connection is lost.
retryingListen :: AppState -> IO ()
retryingListen appState = do
AppState.waitForListenerCanStart appState
AppConfig{..} <- AppState.getConfig appState
let
dbChannel = toS configDbChannel
handleFinally err = do
-- assume we lost notifications, call the connection worker which will also reload the schema cache
-- and will setListenerCanStart again
-- TODO: When the connection error is only on the Listener, it's wasteful to call the connectionWorker everytime.
AppState.connectionWorker appState
AppState.putIsListenerOn appState False
observer $ DBListenFail dbChannel (Right err)
unless configDbPoolAutomaticRecovery $
@@ -60,6 +54,8 @@ retryingListen appState = do
delay <- AppState.getNextListenerDelay appState
when (delay > 1) $ do -- if we did a retry
-- assume we lost notifications, call the connection worker which will also reload the schema cache
AppState.connectionWorker appState
-- reset the delay
AppState.putNextListenerDelay appState 1