Allow schema cache reloading with NOTIFY (#1542)

Fixes https://github.com/PostgREST/postgrest/issues/1512

Helps on environments where you can't send unix signals(Windows, managed
containers). Also provides better UX for schema reloads - NOTIFY
can be sent from pg clients(psql, pgadmin).

`NOTIFY pgrst` - with no payload - should be done to reload the schema cache.
Notifications with a payload will be ignored.

The channel can be enabled with `db-channel-enabled`(false by default)
and its name can be configured with `db-channel`.

The LISTEN thread uses a dedicated pg connection.
This connection is recovered if it fails.
A debounce of 1ms is done in case too many NOTIFYs arrive.
This commit is contained in:
Steve Chavez
2020-06-24 19:00:02 -05:00
committed by GitHub
parent 24064f8626
commit 43d71e95ac
13 changed files with 169 additions and 57 deletions
+2
View File
@@ -267,6 +267,8 @@ workflows:
filters: filters:
tags: tags:
only: /v[0-9]+(\.[0-9]+)*/ only: /v[0-9]+(\.[0-9]+)*/
requires:
- nix-build
- release: - release:
requires: requires:
- style-check - style-check
+1
View File
@@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Added ### Added
- #1525, Allow http status override through response.status guc - @steve-chavez - #1525, Allow http status override through response.status guc - @steve-chavez
- #1512, Allow schema cache reloading with NOTIFY - @steve-chavez
### Fixed ### Fixed
+95 -51
View File
@@ -4,11 +4,17 @@ module Main where
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Base64 as B64
import qualified Hasql.Connection as C
import qualified Hasql.Notifications as N
import qualified Hasql.Pool as P import qualified Hasql.Pool as P
import qualified Hasql.Transaction.Sessions as HT import qualified Hasql.Transaction.Sessions as HT
import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate, import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate,
updateAction) updateAction)
import Control.Debounce (debounceAction, debounceEdge,
debounceFreq,
defaultDebounceSettings, mkDebounce,
trailingEdge)
import Control.Retry (RetryStatus, capDelay, import Control.Retry (RetryStatus, capDelay,
exponentialBackoff, retrying, exponentialBackoff, retrying,
rsPreviousDelay) rsPreviousDelay)
@@ -42,6 +48,12 @@ import System.Posix.Signals
import UnixSocket import UnixSocket
#endif #endif
-- Time constants
_32s :: Int
_32s = 32000000 :: Int -- 32 seconds
_1s :: Int
_1s = 1000000 :: Int -- 1 second
{-| {-|
The purpose of this worker is to fill the refDbStructure created in 'main' The purpose of this worker is to fill the refDbStructure created in 'main'
@@ -58,19 +70,18 @@ import UnixSocket
2. Checks if the pg version is supported and if it's not it kills the main 2. Checks if the pg version is supported and if it's not it kills the main
program. program.
3. Obtains the dbStructure. 3. Obtains the dbStructure.
4. If 2 or 3 fail to give their result it means the connection is down so it
goes back to 1, otherwise it finishes his work successfully.
-} -}
connectionWorker connectionWorker
:: ThreadId -- ^ This thread is killed if pg version is unsupported :: ThreadId -- ^ Main thread id. Killed if pg version is unsupported
-> P.Pool -- ^ The PostgreSQL connection pool -> P.Pool -- ^ The PostgreSQL connection pool
-> [Schema] -- ^ Schemas PostgREST is serving up -> [Schema] -- ^ Schemas PostgREST is serving up
-> IORef (Maybe DbStructure) -- ^ mutable reference to 'DbStructure' -> IORef (Maybe DbStructure) -- ^ mutable reference to 'DbStructure'
-> IORef Bool -- ^ Used as a binary Semaphore -> IORef Bool -- ^ Used as a binary Semaphore
-> (Bool, MVar ConnectionStatus) -- ^ For interacting with the LISTEN channel
-> IO () -> IO ()
connectionWorker mainTid pool schemas refDbStructure refIsWorkerOn = do connectionWorker mainTid pool schemas refDbStructure refIsWorkerOn (dbChannelEnabled, mvarConnectionStatus) = do
isWorkerOn <- readIORef refIsWorkerOn isWorkerOn <- readIORef refIsWorkerOn
unless isWorkerOn $ do unless isWorkerOn $ do -- Prevents multiple workers to be running at the same time. Could happen on too many SIGUSR1s.
atomicWriteIORef refIsWorkerOn True atomicWriteIORef refIsWorkerOn True
void $ forkIO work void $ forkIO work
where where
@@ -78,23 +89,29 @@ connectionWorker mainTid pool schemas refDbStructure refIsWorkerOn = do
atomicWriteIORef refDbStructure Nothing atomicWriteIORef refDbStructure Nothing
putStrLn ("Attempting to connect to the database..." :: Text) putStrLn ("Attempting to connect to the database..." :: Text)
connected <- connectionStatus pool connected <- connectionStatus pool
when dbChannelEnabled $
void $ tryPutMVar mvarConnectionStatus connected -- tryPutMVar doesn't lock the thread. It should always succeed since the worker is the only producer.
case connected of case connected of
FatalConnectionError reason -> hPutStrLn stderr reason FatalConnectionError reason -> hPutStrLn stderr reason >> killThread mainTid -- Fatal error when connecting
>> killThread mainTid -- Fatal error when connecting NotConnected -> return () -- Unreachable because connectionStatus will keep trying to connect
NotConnected -> return () -- Unreachable
Connected actualPgVersion -> do -- Procede with initialization Connected actualPgVersion -> do -- Procede with initialization
result <- P.use pool $ do putStrLn ("Connection successful" :: Text)
dbStructure <- HT.transaction HT.ReadCommitted HT.Read $ getDbStructure schemas actualPgVersion fillSchemaCache pool actualPgVersion schemas refDbStructure
liftIO $ atomicWriteIORef refDbStructure $ Just dbStructure liftIO $ atomicWriteIORef refIsWorkerOn False
fillSchemaCache :: P.Pool -> PgVersion -> [Schema] -> IORef (Maybe DbStructure) -> IO ()
fillSchemaCache pool actualPgVersion schemas refDbStructure = do
result <- P.use pool $ HT.transaction HT.ReadCommitted HT.Read $ getDbStructure schemas actualPgVersion
case result of case result of
Left e -> do Left e -> do
putStrLn ("Failed to query the database. Retrying." :: Text) -- If this error happens it would mean the connection is down again. Improbable because connectionStatus ensured the connection.
-- It's not a problem though, because App.postgrest would retry the connectionWorker or the user can do a SIGSUR1 again.
hPutStrLn stderr . toS . errorPayload $ PgError False e hPutStrLn stderr . toS . errorPayload $ PgError False e
work putStrLn ("Failed to load the schema cache" :: Text)
Right _ -> do Right dbStructure -> do
atomicWriteIORef refIsWorkerOn False atomicWriteIORef refDbStructure $ Just dbStructure
putStrLn ("Connection successful" :: Text) putStrLn ("Schema cache loaded" :: Text)
{-| {-|
Used by 'connectionWorker' to check if the provided db-uri lets Used by 'connectionWorker' to check if the provided db-uri lets
@@ -107,7 +124,7 @@ connectionWorker mainTid pool schemas refDbStructure refIsWorkerOn = do
-} -}
connectionStatus :: P.Pool -> IO ConnectionStatus connectionStatus :: P.Pool -> IO ConnectionStatus
connectionStatus pool = connectionStatus pool =
retrying (capDelay 32000000 $ exponentialBackoff 1000000) retrying (capDelay _32s $ exponentialBackoff _1s)
shouldRetry shouldRetry
(const $ P.release pool >> getConnectionStatus) (const $ P.release pool >> getConnectionStatus)
where where
@@ -129,16 +146,50 @@ connectionStatus pool =
shouldRetry :: RetryStatus -> ConnectionStatus -> IO Bool shouldRetry :: RetryStatus -> ConnectionStatus -> IO Bool
shouldRetry rs isConnSucc = do shouldRetry rs isConnSucc = do
let delay = fromMaybe 0 (rsPreviousDelay rs) `div` 1000000 let delay = fromMaybe 0 (rsPreviousDelay rs) `div` _1s
itShould = NotConnected == isConnSucc itShould = NotConnected == isConnSucc
when itShould $ when itShould $
putStrLn $ "Attempting to reconnect to the database in " <> (show delay::Text) <> " seconds..." putStrLn $ "Attempting to reconnect to the database in " <> (show delay::Text) <> " seconds..."
return itShould return itShould
{-| {-|
This is where everything starts. Starts a dedicated pg connection to LISTEN for notifications.
When a NOTIFY channel(with an empty payload) is done, it refills the schema cache.
It uses the connectionWorker in case the LISTEN connection dies.
-} -}
listener :: ByteString -> Text -> P.Pool -> [Schema] -> IORef (Maybe DbStructure) -> MVar ConnectionStatus -> IO () -> IO ()
listener dbUri dbChannel pool schemas refDbStructure mvarConnectionStatus connWorker = start
where
start = do
connStatus <- takeMVar mvarConnectionStatus -- takeMVar makes the thread wait if the MVar is empty(until there's a connection).
case connStatus of
Connected actualPgVersion -> void $ forkFinally (do -- forkFinally allows to detect if the thread dies
dbOrError <- C.acquire dbUri
-- Debounce in case too many NOTIFYs arrive. Could happen on a migration(assuming a pg EVENT TRIGGER is set up).
scFiller <- mkDebounce (defaultDebounceSettings {
debounceAction = fillSchemaCache pool actualPgVersion schemas refDbStructure,
debounceEdge = trailingEdge, -- wait until the function hasnt been called in _1s
debounceFreq = _1s })
case dbOrError of
Right db -> do
putStrLn $ "Listening for notifications on the " <> dbChannel <> " channel"
let channelToListen = N.toPgIdentifier dbChannel
N.listen db channelToListen
N.waitForNotifications (\_ msg ->
if BS.null msg
then scFiller -- reload the schema cache
else pure ()) db -- Do nothing if anything else than an empty message is sent
_ -> die errorMessage)
(\_ -> do -- if the thread dies, we try to recover
putStrLn retryMessage
connWorker -- assume the pool connection was also lost, call the connection worker
start) -- retry the listener
_ ->
putStrLn errorMessage -- Should be unreachable. connectionStatus will retry until there's a connection.
errorMessage = "Could not listen for notifications on the " <> dbChannel <> " channel" :: Text
retryMessage = "Retrying listening for notifications on the " <> dbChannel <> " channel.." :: Text
-- | This is where everything starts.
main :: IO () main :: IO ()
main = do main = do
-- --
@@ -159,7 +210,8 @@ main = do
proxy = configOpenAPIProxyUri conf proxy = configOpenAPIProxyUri conf
maybeSocketAddr = configSocket conf maybeSocketAddr = configSocket conf
socketFileMode = configSocketMode conf socketFileMode = configSocketMode conf
pgSettings = toS (configDatabase conf) -- is the db-uri dbUri = toS (configDbUri conf)
(dbChannelEnabled, dbChannel) = (configDbChannelEnabled conf, toS $ configDbChannel conf)
roleClaimKey = configRoleClaimKey conf roleClaimKey = configRoleClaimKey conf
appSettings = appSettings =
setHost ((fromString . toS) host) -- Warp settings setHost ((fromString . toS) host) -- Warp settings
@@ -167,7 +219,6 @@ main = do
. setServerName (toS $ "postgrest/" <> prettyVersion) $ . setServerName (toS $ "postgrest/" <> prettyVersion) $
defaultSettings defaultSettings
whenLeft socketFileMode panic whenLeft socketFileMode panic
-- Checks that the provided proxy uri is formated correctly -- Checks that the provided proxy uri is formated correctly
@@ -181,32 +232,32 @@ main = do
-- create connection pool with the provided settings, returns either -- create connection pool with the provided settings, returns either
-- a 'Connection' or a 'ConnectionError'. Does not throw. -- a 'Connection' or a 'ConnectionError'. Does not throw.
pool <- P.acquire (configPool conf, configPoolTimeout' conf, pgSettings) pool <- P.acquire (configPool conf, configPoolTimeout' conf, dbUri)
--
-- Used to sync the listener with the connectionWorker. No connection for the listener at first. Only used if dbChannelEnabled=true.
mvarConnectionStatus <- newEmptyMVar
-- To be filled in by connectionWorker -- To be filled in by connectionWorker
refDbStructure <- newIORef Nothing refDbStructure <- newIORef Nothing
--
-- Helper ref to make sure just one connectionWorker can run at a time -- Helper ref to make sure just one connectionWorker can run at a time
refIsWorkerOn <- newIORef False refIsWorkerOn <- newIORef False
--
-- This is passed to the connectionWorker method so it can kill the main -- This is passed to the connectionWorker method so it can kill the main
-- thread if the PostgreSQL's version is not supported. -- thread if the PostgreSQL's version is not supported.
mainTid <- myThreadId mainTid <- myThreadId
--
-- Sets the refDbStructure let connWorker = connectionWorker mainTid pool schemas refDbStructure refIsWorkerOn (dbChannelEnabled, mvarConnectionStatus)
connectionWorker
mainTid -- Sets the initial refDbStructure
pool connWorker
schemas
refDbStructure
refIsWorkerOn
--
-- Only for systems with signals: -- Only for systems with signals:
-- --
-- releases the connection pool whenever the program is terminated, -- releases the connection pool whenever the program is terminated,
-- see issue #268 -- see https://github.com/PostgREST/postgrest/issues/268
-- --
-- Plus the SIGHUP signal updates the internal 'DbStructure' by running -- Plus the SIGUSR1 signal updates the internal 'DbStructure' by running
-- 'connectionWorker' exactly as before. -- 'connectionWorker' exactly as before.
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
forM_ [sigINT, sigTERM] $ \sig -> forM_ [sigINT, sigTERM] $ \sig ->
@@ -216,15 +267,13 @@ main = do
) Nothing ) Nothing
void $ installHandler sigUSR1 ( void $ installHandler sigUSR1 (
Catch $ connectionWorker Catch connWorker
mainTid
pool
schemas
refDbStructure
refIsWorkerOn
) Nothing ) Nothing
#endif #endif
-- reload schema cache on NOTIFY
when dbChannelEnabled $
listener dbUri dbChannel pool schemas refDbStructure mvarConnectionStatus connWorker
-- ask for the OS time at most once per second -- ask for the OS time at most once per second
getTime <- mkAutoUpdate defaultUpdateSettings {updateAction = getCurrentTime} getTime <- mkAutoUpdate defaultUpdateSettings {updateAction = getCurrentTime}
@@ -235,12 +284,7 @@ main = do
refDbStructure refDbStructure
pool pool
getTime getTime
(connectionWorker connWorker
mainTid
pool
schemas
refDbStructure
refIsWorkerOn)
-- run the postgrest application with user defined socket. Only for UNIX systems. -- run the postgrest application with user defined socket. Only for UNIX systems.
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
@@ -311,14 +355,14 @@ loadSecretFile conf = extractAndTransform mSecret
loadDbUriFile :: AppConfig -> IO AppConfig loadDbUriFile :: AppConfig -> IO AppConfig
loadDbUriFile conf = extractDbUri mDbUri loadDbUriFile conf = extractDbUri mDbUri
where where
mDbUri = configDatabase conf mDbUri = configDbUri conf
extractDbUri :: Text -> IO AppConfig extractDbUri :: Text -> IO AppConfig
extractDbUri dbUri = extractDbUri dbUri =
fmap setDbUri $ fmap setDbUri $
case stripPrefix "@" dbUri of case stripPrefix "@" dbUri of
Nothing -> return dbUri Nothing -> return dbUri
Just filename -> strip <$> readFile (toS filename) Just filename -> strip <$> readFile (toS filename)
setDbUri dbUri = conf {configDatabase = dbUri} setDbUri dbUri = conf {configDbUri = dbUri}
-- Utilitarian functions. -- Utilitarian functions.
whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f () whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f ()
+2
View File
@@ -29,6 +29,8 @@ let
"PGRST_DB_POOL=100" "PGRST_DB_POOL=100"
"PGRST_DB_POOL_TIMEOUT=10" "PGRST_DB_POOL_TIMEOUT=10"
"PGRST_DB_EXTRA_SEARCH_PATH=public" "PGRST_DB_EXTRA_SEARCH_PATH=public"
"PGRST_DB_CHANNEL=pgrst"
"PGRST_DB_CHANNEL_ENABLED=false"
"PGRST_SERVER_HOST=*4" "PGRST_SERVER_HOST=*4"
"PGRST_SERVER_PORT=3000" "PGRST_SERVER_PORT=3000"
"PGRST_OPENAPI_SERVER_PROXY_URI=" "PGRST_OPENAPI_SERVER_PROXY_URI="
+3
View File
@@ -12,6 +12,9 @@ db-pool = "$(PGRST_DB_POOL)"
db-pool-timeout = "$(PGRST_DB_POOL_TIMEOUT)" db-pool-timeout = "$(PGRST_DB_POOL_TIMEOUT)"
db-extra-search-path = "$(PGRST_DB_EXTRA_SEARCH_PATH)" db-extra-search-path = "$(PGRST_DB_EXTRA_SEARCH_PATH)"
db-channel = "$(PGRST_DB_CHANNEL)"
db-channel-enabled = "$(PGRST_DB_CHANNEL_ENABLED)"
server-host = "$(PGRST_SERVER_HOST)" server-host = "$(PGRST_SERVER_HOST)"
server-port = "$(PGRST_SERVER_PORT)" server-port = "$(PGRST_SERVER_PORT)"
+13
View File
@@ -12,6 +12,19 @@ let
ver = "0.3.0"; ver = "0.3.0";
sha256 = "0iwh4wsjhb7pms88lw1afhdal9f86nrrkkvv65f9wxbd1b159n72"; sha256 = "0iwh4wsjhb7pms88lw1afhdal9f86nrrkkvv65f9wxbd1b159n72";
} { }; } { };
# To get the sha256
# nix-prefetch-url --unpack https://hackage.haskell.org/package/hasql-notifications-0.1.0.0/hasql-notifications-0.1.0.0.tar.gz
hasql-notifications =
self.haskell.lib.overrideCabal
(
prev.callHackageDirect
{
pkg = "hasql-notifications";
ver = "0.1.0.0";
sha256 = "1z17gsqvvzzi0yipc3qy3jz8vzpww4vsc4vaj2kbzr2mfliq6fx3";
} { }
)
(old: { doCheck = false; });
} // extraOverrides final prev; } // extraOverrides final prev;
in in
{ {
+3
View File
@@ -31,4 +31,7 @@
# https://github.com/nh2/static-haskell-nix/pull/91 # https://github.com/nh2/static-haskell-nix/pull/91
static-haskell-nix-postgrest-openssl-linking-fix = static-haskell-nix-postgrest-openssl-linking-fix =
./static-haskell-nix-postgrest-openssl-linking-fix.patch; ./static-haskell-nix-postgrest-openssl-linking-fix.patch;
static-haskell-nix-hasql-notifications-openssl-linking-fix =
./static-haskell-nix-hasql-notifications-openssl-linking-fix.patch;
} }
@@ -0,0 +1,28 @@
From 49ecb703d9d0bfd38eb69ba5cb63a8262bd03f96 Mon Sep 17 00:00:00 2001
From: steve-chavez <stevechavezast@gmail.com>
Date: Thu, 11 Jun 2020 13:18:07 -0500
Subject: [PATCH] Add hasql-notifications openssl linking fix
---
survey/default.nix | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/survey/default.nix b/survey/default.nix
index 828beaa..9c2d5f6 100644
--- a/survey/default.nix
+++ b/survey/default.nix
@@ -1054,6 +1054,11 @@ let
super.squeal-postgresql
[ final.openssl ]
"--libs openssl";
+ hasql-notifications =
+ addStaticLinkerFlagsWithPkgconfig
+ super.hasql-notifications
+ [ final.openssl ]
+ "--libs openssl";
xml-to-json =
addStaticLinkerFlagsWithPkgconfig
--
2.19.3
+1
View File
@@ -18,6 +18,7 @@ let
static-haskell-nix static-haskell-nix
[ [
patches.static-haskell-nix-postgrest-openssl-linking-fix patches.static-haskell-nix-postgrest-openssl-linking-fix
patches.static-haskell-nix-hasql-notifications-openssl-linking-fix
]; ];
patchedNixpkgs = patchedNixpkgs =
+1
View File
@@ -112,6 +112,7 @@ executable postgrest
, hasql >= 1.4 && < 1.5 , hasql >= 1.4 && < 1.5
, hasql-pool >= 0.5 && < 0.6 , hasql-pool >= 0.5 && < 0.6
, hasql-transaction >= 0.7.2 && < 1.1 , hasql-transaction >= 0.7.2 && < 1.1
, hasql-notifications == 0.1.0.0
, network < 3.2 , network < 3.2
, postgrest , postgrest
, protolude >= 0.3 && < 0.4 , protolude >= 0.3 && < 0.4
+10 -1
View File
@@ -67,7 +67,7 @@ import Protolude.Conv (toS)
-- | Config file settings for the server -- | Config file settings for the server
data AppConfig = AppConfig { data AppConfig = AppConfig {
configDatabase :: Text configDbUri :: Text
, configAnonRole :: Text , configAnonRole :: Text
, configOpenAPIProxyUri :: Maybe Text , configOpenAPIProxyUri :: Maybe Text
, configSchemas :: NonEmpty Text , configSchemas :: NonEmpty Text
@@ -75,6 +75,8 @@ data AppConfig = AppConfig {
, configPort :: Int , configPort :: Int
, configSocket :: Maybe FilePath , configSocket :: Maybe FilePath
, configSocketMode :: Either Text FileMode , configSocketMode :: Either Text FileMode
, configDbChannel :: Text
, configDbChannelEnabled :: Bool
, configJwtSecret :: Maybe B.ByteString , configJwtSecret :: Maybe B.ByteString
, configJwtSecretIsBase64 :: Bool , configJwtSecretIsBase64 :: Bool
@@ -163,6 +165,8 @@ readOptions = do
<*> (fromMaybe 3000 <$> optInt "server-port") <*> (fromMaybe 3000 <$> optInt "server-port")
<*> (fmap unpack <$> optString "server-unix-socket") <*> (fmap unpack <$> optString "server-unix-socket")
<*> parseSocketFileMode "server-unix-socket-mode" <*> parseSocketFileMode "server-unix-socket-mode"
<*> (fromMaybe "pgrst" <$> optString "db-channel")
<*> ((Just True ==) <$> optBool "db-channel-enabled")
<*> (fmap encodeUtf8 <$> optString "jwt-secret") <*> (fmap encodeUtf8 <$> optString "jwt-secret")
<*> ((Just True ==) <$> optBool "secret-is-base64") <*> ((Just True ==) <$> optBool "secret-is-base64")
<*> parseJwtAudience "jwt-aud" <*> parseJwtAudience "jwt-aud"
@@ -276,6 +280,11 @@ readOptions = do
|## when none is provided, 660 is applied by default |## when none is provided, 660 is applied by default
|# server-unix-socket-mode = "660" |# server-unix-socket-mode = "660"
| |
|## Notification channel for reloading the schema cache
|# db-channel = "pgrst"
|## Enable or disable the notification channel
|# db-channel-enabled = false
|
|## base url for swagger output |## base url for swagger output
|# openapi-server-proxy-uri = "" |# openapi-server-proxy-uri = ""
| |
+1
View File
@@ -12,3 +12,4 @@ extra-deps:
- hspec-wai-json-0.10.1@sha256:67b405c38f0a9e2771480c8d3ecd8aeb8d8776a35d3b2906cb1b76c9538617e4,1629 - hspec-wai-json-0.10.1@sha256:67b405c38f0a9e2771480c8d3ecd8aeb8d8776a35d3b2906cb1b76c9538617e4,1629
- interpolatedstring-perl6-1.0.2@sha256:7ce49c8a69a2a1b89c001ed79db2aab656ffd0faf2a7a701a553b6deb5c8ba7f,1073 - interpolatedstring-perl6-1.0.2@sha256:7ce49c8a69a2a1b89c001ed79db2aab656ffd0faf2a7a701a553b6deb5c8ba7f,1073
- protolude-0.3.0@sha256:8361b811b420585b122a7ba715aa5923834db6e8c36309bf267df2dbf66b95ef,2693 - protolude-0.3.0@sha256:8361b811b420585b122a7ba715aa5923834db6e8c36309bf267df2dbf66b95ef,2693
- hasql-notifications-0.1.0.0@sha256:9ab112d2bb5da0d55abd65f0d27a7bb1dc4aeb792518d9a2ea8a16e243e19985,2156
+5 -1
View File
@@ -69,6 +69,10 @@ _baseCfg = -- Connection Settings
Nothing Nothing
-- No user configured Unix Socket file mode (defaults to 660) -- No user configured Unix Socket file mode (defaults to 660)
(Right 432) (Right 432)
-- db-channel
"pgrst"
-- db-channel-enabled
False
-- Jwt settings -- Jwt settings
(Just $ encodeUtf8 "reallyreallyreallyreallyverysafe") False Nothing (Just $ encodeUtf8 "reallyreallyreallyreallyverysafe") False Nothing
-- Connection Modifiers -- Connection Modifiers
@@ -88,7 +92,7 @@ _baseCfg = -- Connection Settings
[] []
testCfg :: Text -> AppConfig testCfg :: Text -> AppConfig
testCfg testDbConn = _baseCfg { configDatabase = testDbConn } testCfg testDbConn = _baseCfg { configDbUri = testDbConn }
testCfgNoJWT :: Text -> AppConfig testCfgNoJWT :: Text -> AppConfig
testCfgNoJWT testDbConn = (testCfg testDbConn) { configJwtSecret = Nothing } testCfgNoJWT testDbConn = (testCfg testDbConn) { configJwtSecret = Nothing }