Skip to content

Commit e9cd961

Browse files
authored
Merge pull request #65 from diogob/configurable-retries
Add configuration for max number of retries and exit server with an error when connection dies or fails to open
2 parents 27b0c24 + a13614f commit e9cd961

File tree

5 files changed

+24
-17
lines changed

5 files changed

+24
-17
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 0.9.0.0
4+
5+
- Add PGWS_RETRIES to limit the amount of times the server tries to open a database connection upon startup (defaults to 5). This breaks backward compatibility if you rely on the behaviour of the server to try infitite times.
6+
37
## 0.8.0.1
48

59
- Fix compilation error due to missing version upper bound for protolude.

postgres-websockets.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: postgres-websockets
2-
version: 0.8.0.1
2+
version: 0.9.0.0
33
synopsis: Middleware to map LISTEN/NOTIFY messages to Websockets
44
description: Please see README.md
55
homepage: https://github.com/diogob/postgres-websockets#readme

src/PostgresWebsockets/Config.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ data AppConfig = AppConfig {
3434
, configJwtSecret :: ByteString
3535
, configJwtSecretIsBase64 :: Bool
3636
, configPool :: Int
37+
, configRetries :: Int
3738
}
3839

3940
-- | User friendly version number
@@ -70,6 +71,7 @@ readOptions =
7071
<*> var str "PGWS_JWT_SECRET" (help "Secret used to sign JWT tokens used to open communications channels")
7172
<*> var auto "PGWS_JWT_SECRET_BASE64" (def False <> helpDef show <> help "Indicate whether the JWT secret should be decoded from a base64 encoded string")
7273
<*> var auto "PGWS_POOL_SIZE" (def 10 <> helpDef show <> help "How many connection to the database should be used by the connection pool")
74+
<*> var auto "PGWS_RETRIES" (def 5 <> helpDef show <> help "How many times it should try to connect to the database on startup before exiting with an error")
7375

7476
loadSecretFile :: AppConfig -> IO AppConfig
7577
loadSecretFile conf = extractAndTransform secret

src/PostgresWebsockets/HasqlBroadcast.hs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ import Data.Aeson (decode, Value(..))
2323
import Data.HashMap.Lazy (lookupDefault)
2424
import Data.Either.Combinators (mapBoth)
2525
import Data.Function (id)
26-
import Control.Retry (RetryStatus, retrying, capDelay, exponentialBackoff)
26+
import Control.Retry (RetryStatus(..), retrying, capDelay, exponentialBackoff)
2727

2828
import PostgresWebsockets.Broadcast
2929

3030
{- | Returns a multiplexer from a connection URI, keeps trying to connect in case there is any error.
3131
This function also spawns a thread that keeps relaying the messages from the database to the multiplexer's listeners
3232
-}
33-
newHasqlBroadcaster :: IO () -> Text -> ByteString -> IO Multiplexer
34-
newHasqlBroadcaster onConnectionFailure ch = newHasqlBroadcasterForConnection . tryUntilConnected
33+
newHasqlBroadcaster :: IO () -> Text -> Int -> ByteString -> IO Multiplexer
34+
newHasqlBroadcaster onConnectionFailure ch maxRetries = newHasqlBroadcasterForConnection . tryUntilConnected maxRetries
3535
where
3636
newHasqlBroadcasterForConnection = newHasqlBroadcasterForChannel onConnectionFailure ch
3737

@@ -44,20 +44,20 @@ newHasqlBroadcasterOrError onConnectionFailure ch =
4444
where
4545
newHasqlBroadcasterForConnection = newHasqlBroadcasterForChannel onConnectionFailure ch
4646

47-
tryUntilConnected :: ByteString -> IO Connection
48-
tryUntilConnected =
47+
tryUntilConnected :: Int -> ByteString -> IO Connection
48+
tryUntilConnected maxRetries =
4949
fmap (either (panic "Failure on connection retry") id) . retryConnection
5050
where
5151
retryConnection conStr = retrying retryPolicy shouldRetry (const $ acquire conStr)
5252
maxDelayInMicroseconds = 32000000
5353
firstDelayInMicroseconds = 1000000
5454
retryPolicy = capDelay maxDelayInMicroseconds $ exponentialBackoff firstDelayInMicroseconds
5555
shouldRetry :: RetryStatus -> Either ConnectionError Connection -> IO Bool
56-
shouldRetry _ con =
56+
shouldRetry RetryStatus{..} con =
5757
case con of
5858
Left err -> do
5959
putErrLn $ "Error connecting notification listener to database: " <> show err
60-
return True
60+
pure $ rsIterNumber < maxRetries - 1
6161
_ -> return False
6262

6363
{- | Returns a multiplexer from a channel and an IO Connection, listen for different database notifications on the provided channel using the connection produced.

src/PostgresWebsockets/Server.hs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,24 @@ import Network.Wai.Middleware.RequestLogger (logStdout)
2525

2626
-- | Start a stand-alone warp server using the parameters from AppConfig and a opening a database connection pool.
2727
serve :: AppConfig -> IO ()
28-
serve conf = do
28+
serve conf@AppConfig{..} = do
2929
shutdownSignal <- newEmptyMVar
30-
let listenChannel = toS $ configListenChannel conf
31-
pgSettings = toS (configDatabase conf)
32-
waitForShutdown cl = void $ forkIO (takeMVar shutdownSignal >> cl >> die "Shutting server down...")
30+
let listenChannel = toS configListenChannel
31+
pgSettings = toS configDatabase
32+
waitForShutdown cl = void $ forkIO (takeMVar shutdownSignal >> cl)
3333
appSettings = warpSettings waitForShutdown conf
3434

35-
putStrLn $ ("Listening on port " :: Text) <> show (configPort conf)
35+
putStrLn $ ("Listening on port " :: Text) <> show configPort
3636

3737
let shutdown = putErrLn ("Broadcaster connection is dead" :: Text) >> putMVar shutdownSignal ()
38-
pool <- P.acquire (configPool conf, 10, pgSettings)
39-
multi <- newHasqlBroadcaster shutdown listenChannel pgSettings
38+
pool <- P.acquire (configPool, 10, pgSettings)
39+
multi <- newHasqlBroadcaster shutdown listenChannel configRetries pgSettings
4040
getTime <- mkGetTime
4141

4242
runSettings appSettings $
43-
postgresWsMiddleware getTime listenChannel (configJwtSecret conf) pool multi $
44-
logStdout $ maybe dummyApp staticApp' (configPath conf)
43+
postgresWsMiddleware getTime listenChannel configJwtSecret pool multi $
44+
logStdout $ maybe dummyApp staticApp' configPath
45+
die "Shutting down server..."
4546

4647
where
4748
mkGetTime :: IO (IO UTCTime)

0 commit comments

Comments
 (0)