Skip to content

Commit 8b15180

Browse files
committed
add(observation): db pool flushes observation
DISCLAIMER: This commit was authored entirely by a human without the assistance of LLMs. Emit a dedicated PoolFlushed observation when the DB pool is released during schema cache reload.
1 parent 0698f94 commit 8b15180

6 files changed

Lines changed: 67 additions & 1 deletion

File tree

postgrest.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ test-suite spec
259259
Feature.Query.UpsertSpec
260260
Feature.RollbackSpec
261261
Feature.RpcPreRequestGucsSpec
262+
Feature.SchemaCacheSpec
262263
SpecHelper
263264
build-depends: base >= 4.9 && < 4.20
264265
, aeson >= 2.0.3 && < 2.3

src/PostgREST/AppState.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,14 @@ usePool AppState{stateObserver=observer, stateMainThreadId=mainThreadId, ..} ses
219219

220220
-- | Flush the connection pool so that any future use of the pool will
221221
-- use connections freshly established after this call.
222+
-- | Emits PoolFlushed observation
222223
flushPool :: AppState -> IO ()
223-
flushPool AppState{..} = SQL.release statePool
224+
flushPool AppState{..} = do
225+
SQL.release statePool
226+
stateObserver PoolFlushed
224227

225228
-- | Destroy the pool on shutdown.
229+
-- | Differs from flushPool in not emiting PoolFlushed observation.
226230
destroyPool :: AppState -> IO ()
227231
destroyPool AppState{..} = SQL.release statePool
228232

src/PostgREST/Logger.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ observationLogger loggerState logLevel obs = case obs of
111111
o@PoolRequestFullfilled ->
112112
when (logLevel >= LogDebug) $ do
113113
logWithZTime loggerState $ observationMessages o
114+
o@PoolFlushed ->
115+
when (logLevel >= LogDebug) $ do
116+
logWithZTime loggerState $ observationMessages o
114117
o@JwtCacheEviction ->
115118
when (logLevel >= LogDebug) $ do
116119
logWithZTime loggerState $ observationMessages o
@@ -224,6 +227,8 @@ observationMessages = \case
224227
pure "Trying to borrow a connection from pool"
225228
PoolRequestFullfilled ->
226229
pure "Borrowed a connection from the pool"
230+
PoolFlushed ->
231+
pure "Database connection pool flushed"
227232
JwtCacheLookup _ ->
228233
pure "Looked up a JWT in JWT cache"
229234
JwtCacheEviction ->

src/PostgREST/Observation.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ data Observation
5353
| HasqlPoolObs SQL.Observation
5454
| PoolRequest
5555
| PoolRequestFullfilled
56+
| PoolFlushed
5657
| JwtCacheLookup Bool
5758
| JwtCacheEviction
5859
| WarpErrorObs Text
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{-# LANGUAGE DataKinds #-}
2+
{-# LANGUAGE MonadComprehensions #-}
3+
{-# LANGUAGE NamedFieldPuns #-}
4+
module Feature.SchemaCacheSpec where
5+
6+
import Network.Wai (Application)
7+
import qualified PostgREST.AppState as AppState
8+
import PostgREST.Config (configDbSchemas)
9+
import PostgREST.Observation
10+
import Protolude
11+
import SpecHelper
12+
import Test.Hspec (SpecWith, describe, it)
13+
import Test.Hspec.Wai (getState)
14+
15+
spec :: SpecWith (SpecState, Application)
16+
spec = describe "Server started with metrics enabled" $ do
17+
18+
it "Should emit PoolFlushed, SchemaCacheQueriedObs and SchemaCacheLoadedObs when schema cache is reloaded" $ do
19+
SpecState{specAppState = appState, specObsChan} <- getState
20+
let waitFor = waitForObs specObsChan
21+
22+
liftIO $ do
23+
AppState.schemaCacheLoader appState
24+
25+
waitFor (1 * sec) "PoolFlushed" $ \x -> [ o | o@PoolFlushed <- pure x ]
26+
waitFor (1 * sec) "SchemaCacheQueriedObs" $ \x -> [ o | o@SchemaCacheQueriedObs{} <- pure x ]
27+
waitFor (1 * sec) "SchemaCacheLoadedObs" $ \x -> [ o | o@SchemaCacheLoadedObs{} <- pure x ]
28+
29+
30+
it "Should flush pool multiple times when schema reloading retries" $ do
31+
SpecState{specAppState = appState, specObsChan} <- getState
32+
let waitFor = waitForObs specObsChan
33+
34+
liftIO $ do
35+
AppState.getConfig appState >>= \cfg -> do
36+
AppState.putConfig appState $ cfg { configDbSchemas = pure "bad_schema" }
37+
AppState.schemaCacheLoader appState
38+
39+
waitFor (1 * sec) "PoolFlushed 1" $ \x -> [ o | o@PoolFlushed <- pure x ]
40+
waitFor (1 * sec) "SchemaCacheErrorObs" $ \x -> [ o | o@SchemaCacheErrorObs{} <- pure x ]
41+
42+
-- Restore configuration
43+
AppState.putConfig appState cfg
44+
45+
-- Wait for 2 seconds so that retry can happen
46+
waitFor (2 * sec) "PoolFlushed 2" $ \x -> [ o | o@PoolFlushed <- pure x ]
47+
waitFor (1 * sec) "SchemaCacheQueriedObs" $ \x -> [ o | o@SchemaCacheQueriedObs{} <- pure x ]
48+
waitFor (1 * sec) "SchemaCacheLoadedObs" $ \x -> [ o | o@SchemaCacheLoadedObs{} <- pure x ]
49+
50+
where
51+
sec = 1000000

test/spec/Main.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import qualified Feature.Query.UpdateSpec
6969
import qualified Feature.Query.UpsertSpec
7070
import qualified Feature.RollbackSpec
7171
import qualified Feature.RpcPreRequestGucsSpec
72+
import qualified Feature.SchemaCacheSpec
7273
import PostgREST.Observation (Observation (HasqlPoolObs))
7374

7475

@@ -300,6 +301,9 @@ main = do
300301
before observationsApp $
301302
describe "Feature.MetricsSpec" Feature.MetricsSpec.spec
302303

304+
before observationsApp $
305+
describe "Feature.SchemaCacheSpec" Feature.SchemaCacheSpec.spec
306+
303307
where
304308
loadSCache pool conf =
305309
either (panic.show) id <$> P.use pool (HT.transaction HT.ReadCommitted HT.Read $ querySchemaCache conf)

0 commit comments

Comments
 (0)