Skip to content

Commit 5f0d4be

Browse files
committed
fix: Add random delay in Listener.cacheReloader
Triggering schema cache reload immediately upon receival of notification by the listener leads to thundering herd problem in PostgREST cluster. This change adds random delay between 0 and 1 seconds between notification retrieval and schema cache reload triggering.
1 parent 99984d3 commit 5f0d4be

2 files changed

Lines changed: 9 additions & 1 deletion

File tree

postgrest.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ library
158158
, stm-hamt >= 1.2 && < 2
159159
, focus >= 1.0 && < 2
160160
, some >= 1.0.4.1 && < 2
161+
, MonadRandom >= 0.6.2 && < 0.7
161162
-- -fno-spec-constr may help keep compile time memory use in check,
162163
-- see https://gitlab.haskell.org/ghc/ghc/issues/16017#note_219304
163164
-- -optP-Wno-nonportable-include-path

src/PostgREST/Listener.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import qualified PostgREST.AppState as AppState
1818
import qualified PostgREST.Config as Config
1919

2020
import Control.Arrow ((&&&))
21+
import Control.Monad.Random
2122
import Data.Bitraversable (bisequence)
2223
import Data.Either.Combinators (whenRight)
2324
import qualified Database.PostgreSQL.LibPQ as LibPQ
@@ -102,7 +103,13 @@ retryingListen appState = do
102103
| msg == "reload config" -> observer (DBListenerGotConfigMsg channel) >> AppState.readInDbConfig False appState
103104
| otherwise -> pure () -- Do nothing if anything else than an empty message is sent
104105

105-
cacheReloader =
106+
-- add a random delay between 0 and 1 second to avoid thundering herd problem
107+
-- if multiple listeners receive the same notification at the same time
108+
-- the cacheReloader is launched in a separate thread to avoid blocking the listener
109+
-- during the random delay
110+
cacheReloader = void $ forkIO $ do
111+
delay <- getRandomR (0, 1000000)
112+
threadDelay delay
106113
AppState.schemaCacheLoader appState
107114

108115
releaseConnection = void . forkIO . handle (observer . DBListenerConnectionCleanupFail) . SQL.release

0 commit comments

Comments
 (0)