62 lines
2.2 KiB
Haskell
62 lines
2.2 KiB
Haskell
module PostgREST.Unix
|
|
( runAppInSocket
|
|
, installSignalHandlers
|
|
) where
|
|
|
|
import qualified Network.Socket as Socket
|
|
import qualified Network.Wai.Handler.Warp as Warp
|
|
import qualified System.Posix.Signals as Signals
|
|
|
|
import Network.Wai (Application)
|
|
import System.Directory (removeFile)
|
|
import System.IO.Error (isDoesNotExistError)
|
|
import System.Posix.Files (setFileMode)
|
|
import System.Posix.Types (FileMode)
|
|
|
|
import qualified PostgREST.AppState as AppState
|
|
import qualified PostgREST.Workers as Workers
|
|
|
|
import Protolude
|
|
|
|
|
|
-- | Run the PostgREST application with user defined socket.
|
|
runAppInSocket :: Warp.Settings -> Application -> FileMode -> FilePath -> IO ()
|
|
runAppInSocket settings app socketFileMode socketFilePath = do
|
|
sock <- createAndBindSocket
|
|
putStrLn $ ("Listening on unix socket " :: Text) <> show socketFilePath
|
|
Socket.listen sock Socket.maxListenQueue
|
|
Warp.runSettingsSocket settings sock app
|
|
Socket.close sock
|
|
where
|
|
createAndBindSocket = do
|
|
deleteSocketFileIfExist socketFilePath
|
|
sock <- Socket.socket Socket.AF_UNIX Socket.Stream Socket.defaultProtocol
|
|
Socket.bind sock $ Socket.SockAddrUnix socketFilePath
|
|
setFileMode socketFilePath socketFileMode
|
|
return sock
|
|
|
|
deleteSocketFileIfExist path =
|
|
removeFile path `catch` handleDoesNotExist
|
|
|
|
handleDoesNotExist e
|
|
| isDoesNotExistError e = return ()
|
|
| otherwise = throwIO e
|
|
|
|
-- | Set signal handlers, only for systems with signals
|
|
installSignalHandlers :: AppState.AppState -> IO ()
|
|
installSignalHandlers appState = do
|
|
-- Releases the connection pool whenever the program is terminated,
|
|
-- see https://github.com/PostgREST/postgrest/issues/268
|
|
install Signals.sigINT $ AppState.releasePool appState
|
|
install Signals.sigTERM $ AppState.releasePool appState
|
|
|
|
-- The SIGUSR1 signal updates the internal 'DbStructure' by running
|
|
-- 'connectionWorker' exactly as before.
|
|
install Signals.sigUSR1 $ Workers.connectionWorker appState
|
|
|
|
-- Re-read the config on SIGUSR2
|
|
install Signals.sigUSR2 $ Workers.reReadConfig False appState
|
|
where
|
|
install signal handler =
|
|
void $ Signals.installHandler signal (Signals.Catch handler) Nothing
|