2018-06-27 16:11:32 +03:00
|
|
|
module Main where
|
|
|
|
|
2019-03-01 12:17:22 +03:00
|
|
|
import Migrate (migrateCatalog)
|
2018-06-27 16:11:32 +03:00
|
|
|
import Ops
|
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
import Control.Monad.STM (atomically)
|
2018-06-27 16:11:32 +03:00
|
|
|
import Data.Time.Clock (getCurrentTime)
|
|
|
|
import Options.Applicative
|
2018-12-14 06:21:41 +03:00
|
|
|
import System.Environment (getEnvironment, lookupEnv)
|
2018-12-19 14:38:33 +03:00
|
|
|
import System.Exit (exitFailure)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-03-12 08:46:27 +03:00
|
|
|
|
2018-07-27 12:34:50 +03:00
|
|
|
import qualified Control.Concurrent as C
|
2018-06-27 16:11:32 +03:00
|
|
|
import qualified Data.Aeson as A
|
|
|
|
import qualified Data.ByteString.Char8 as BC
|
|
|
|
import qualified Data.ByteString.Lazy as BL
|
|
|
|
import qualified Data.ByteString.Lazy.Char8 as BLC
|
|
|
|
import qualified Data.Text as T
|
2019-05-08 10:36:43 +03:00
|
|
|
import qualified Data.Time.Clock as Clock
|
2018-06-27 16:11:32 +03:00
|
|
|
import qualified Data.Yaml as Y
|
2018-07-27 12:34:50 +03:00
|
|
|
import qualified Network.HTTP.Client as HTTP
|
|
|
|
import qualified Network.HTTP.Client.TLS as HTTP
|
|
|
|
import qualified Network.Wai.Handler.Warp as Warp
|
2019-08-26 08:31:27 +03:00
|
|
|
import qualified System.Posix.Signals as Signals
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-04-17 12:48:41 +03:00
|
|
|
import Hasura.Db
|
2018-09-05 14:26:46 +03:00
|
|
|
import Hasura.Events.Lib
|
2019-03-12 08:46:27 +03:00
|
|
|
import Hasura.Logging
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.Prelude
|
|
|
|
import Hasura.RQL.DDL.Metadata (fetchMetadata)
|
2019-04-29 09:22:48 +03:00
|
|
|
import Hasura.RQL.Types (SQLGenCtx (..), SchemaCache (..),
|
|
|
|
adminUserInfo, emptySchemaCache)
|
2019-09-19 15:54:40 +03:00
|
|
|
import Hasura.Server.App (HasuraApp (..),
|
|
|
|
SchemaCacheRef (..), getSCFromRef,
|
|
|
|
logInconsObjs, mkWaiApp)
|
2018-09-27 14:22:49 +03:00
|
|
|
import Hasura.Server.Auth
|
2018-07-27 12:34:50 +03:00
|
|
|
import Hasura.Server.CheckUpdates (checkForUpdates)
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.Server.Init
|
2019-03-12 08:46:27 +03:00
|
|
|
import Hasura.Server.Logging
|
2018-12-13 10:26:15 +03:00
|
|
|
import Hasura.Server.Query (peelRun)
|
2019-03-12 08:46:27 +03:00
|
|
|
import Hasura.Server.SchemaUpdate
|
2019-01-28 16:55:28 +03:00
|
|
|
import Hasura.Server.Telemetry
|
2018-12-14 06:21:41 +03:00
|
|
|
import Hasura.Server.Version (currentVersion)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
import qualified Database.PG.Query as Q
|
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
printErrExit :: forall a . String -> IO a
|
|
|
|
printErrExit = (>> exitFailure) . putStrLn
|
|
|
|
|
|
|
|
printErrJExit :: A.ToJSON a => forall b . a -> IO b
|
|
|
|
printErrJExit = (>> exitFailure) . printJSON
|
|
|
|
|
|
|
|
parseHGECommand :: Parser RawHGECommand
|
|
|
|
parseHGECommand =
|
2018-12-14 06:21:41 +03:00
|
|
|
subparser
|
2018-12-19 14:38:33 +03:00
|
|
|
( command "serve" (info (helper <*> (HCServe <$> serveOpts))
|
2018-12-14 06:21:41 +03:00
|
|
|
( progDesc "Start the GraphQL Engine Server"
|
|
|
|
<> footerDoc (Just serveCmdFooter)
|
|
|
|
))
|
2018-12-19 14:38:33 +03:00
|
|
|
<> command "export" (info (pure HCExport)
|
2018-12-14 06:21:41 +03:00
|
|
|
( progDesc "Export graphql-engine's metadata to stdout" ))
|
2018-12-19 14:38:33 +03:00
|
|
|
<> command "clean" (info (pure HCClean)
|
2018-12-14 06:21:41 +03:00
|
|
|
( progDesc "Clean graphql-engine's metadata to start afresh" ))
|
2018-12-19 14:38:33 +03:00
|
|
|
<> command "execute" (info (pure HCExecute)
|
2018-12-14 06:21:41 +03:00
|
|
|
( progDesc "Execute a query" ))
|
2018-12-19 14:38:33 +03:00
|
|
|
<> command "version" (info (pure HCVersion)
|
2018-12-14 06:21:41 +03:00
|
|
|
(progDesc "Prints the version of GraphQL Engine"))
|
|
|
|
)
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2018-12-19 14:38:33 +03:00
|
|
|
serveOpts = RawServeOptions
|
|
|
|
<$> parseServerPort
|
2019-01-11 14:07:13 +03:00
|
|
|
<*> parseServerHost
|
2018-12-19 14:38:33 +03:00
|
|
|
<*> parseConnParams
|
|
|
|
<*> parseTxIsolation
|
2019-02-14 12:37:47 +03:00
|
|
|
<*> (parseAdminSecret <|> parseAccessKey)
|
2018-12-19 14:38:33 +03:00
|
|
|
<*> parseWebHook
|
|
|
|
<*> parseJwtSecret
|
|
|
|
<*> parseUnAuthRole
|
|
|
|
<*> parseCorsConfig
|
|
|
|
<*> parseEnableConsole
|
2019-05-16 10:45:29 +03:00
|
|
|
<*> parseConsoleAssetsDir
|
2019-01-28 16:55:28 +03:00
|
|
|
<*> parseEnableTelemetry
|
2019-03-04 10:46:53 +03:00
|
|
|
<*> parseWsReadCookie
|
2019-03-01 14:45:04 +03:00
|
|
|
<*> parseStringifyNum
|
2019-02-28 16:53:03 +03:00
|
|
|
<*> parseEnabledAPIs
|
2019-04-17 12:48:41 +03:00
|
|
|
<*> parseMxRefetchInt
|
|
|
|
<*> parseMxBatchSize
|
2019-05-16 09:13:25 +03:00
|
|
|
<*> parseEnableAllowlist
|
2019-07-11 08:37:06 +03:00
|
|
|
<*> parseEnabledLogs
|
|
|
|
<*> parseLogLevel
|
2018-12-19 14:38:33 +03:00
|
|
|
|
2019-03-04 10:46:53 +03:00
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
parseArgs :: IO HGEOptions
|
|
|
|
parseArgs = do
|
|
|
|
rawHGEOpts <- execParser opts
|
|
|
|
env <- getEnvironment
|
|
|
|
let eitherOpts = runWithEnv env $ mkHGEOptions rawHGEOpts
|
|
|
|
either printErrExit return eitherOpts
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2018-12-19 14:38:33 +03:00
|
|
|
opts = info (helper <*> hgeOpts)
|
2018-06-27 16:11:32 +03:00
|
|
|
( fullDesc <>
|
2018-12-14 06:21:41 +03:00
|
|
|
header "Hasura GraphQL Engine: Realtime GraphQL API over Postgres with access control" <>
|
|
|
|
footerDoc (Just mainCmdFooter)
|
|
|
|
)
|
2018-12-19 14:38:33 +03:00
|
|
|
hgeOpts = HGEOptionsG <$> parseRawConnInfo <*> parseHGECommand
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
printJSON :: (A.ToJSON a) => a -> IO ()
|
|
|
|
printJSON = BLC.putStrLn . A.encode
|
|
|
|
|
|
|
|
printYaml :: (A.ToJSON a) => a -> IO ()
|
|
|
|
printYaml = BC.putStrLn . Y.encode
|
|
|
|
|
2019-03-12 08:46:27 +03:00
|
|
|
mkPGLogger :: Logger -> Q.PGLogger
|
|
|
|
mkPGLogger (Logger logger) (Q.PLERetryMsg msg) =
|
|
|
|
logger $ PGLog LevelWarn msg
|
|
|
|
|
2018-06-27 16:11:32 +03:00
|
|
|
main :: IO ()
|
2018-07-20 10:22:46 +03:00
|
|
|
main = do
|
2018-12-19 14:38:33 +03:00
|
|
|
(HGEOptionsG rci hgeCmd) <- parseArgs
|
|
|
|
-- global http manager
|
2018-07-27 12:34:50 +03:00
|
|
|
httpManager <- HTTP.newManager HTTP.tlsManagerSettings
|
2019-07-31 12:01:48 +03:00
|
|
|
instanceId <- generateInstanceId
|
2018-12-19 14:38:33 +03:00
|
|
|
case hgeCmd of
|
2019-04-17 12:48:41 +03:00
|
|
|
HCServe so@(ServeOptions port host cp isoL mAdminSecret mAuthHook
|
2019-05-16 10:45:29 +03:00
|
|
|
mJwtSecret mUnAuthRole corsCfg enableConsole consoleAssetsDir
|
2019-07-11 08:37:06 +03:00
|
|
|
enableTelemetry strfyNum enabledAPIs lqOpts enableAL
|
|
|
|
enabledLogs serverLogLevel) -> do
|
|
|
|
|
2019-04-17 19:29:39 +03:00
|
|
|
let sqlGenCtx = SQLGenCtx strfyNum
|
2019-05-08 10:36:43 +03:00
|
|
|
|
2019-07-11 08:37:06 +03:00
|
|
|
(loggerCtx, logger, pgLogger) <- mkLoggers enabledLogs serverLogLevel
|
|
|
|
|
2019-05-08 10:36:43 +03:00
|
|
|
initTime <- Clock.getCurrentTime
|
2019-01-02 14:24:17 +03:00
|
|
|
-- log serve options
|
|
|
|
unLogger logger $ serveOptsToLog so
|
2019-07-11 08:37:06 +03:00
|
|
|
hloggerCtx <- mkLoggerCtx (defaultLoggerSettings False serverLogLevel) enabledLogs
|
2018-09-27 14:22:49 +03:00
|
|
|
|
2019-02-14 12:37:47 +03:00
|
|
|
authModeRes <- runExceptT $ mkAuthMode mAdminSecret mAuthHook mJwtSecret
|
2018-12-14 06:21:41 +03:00
|
|
|
mUnAuthRole httpManager loggerCtx
|
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
am <- either (printErrExit . T.unpack) return authModeRes
|
2019-01-02 14:24:17 +03:00
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
ci <- procConnInfo rci
|
2019-09-06 01:59:26 +03:00
|
|
|
|
2019-01-02 14:24:17 +03:00
|
|
|
-- log postgres connection info
|
|
|
|
unLogger logger $ connInfoToLog ci
|
2019-01-28 16:55:28 +03:00
|
|
|
|
2019-03-12 08:46:27 +03:00
|
|
|
pool <- Q.initPGPool ci cp pgLogger
|
|
|
|
|
2019-01-02 14:24:17 +03:00
|
|
|
-- safe init catalog
|
2019-07-31 12:01:48 +03:00
|
|
|
dbId <- initialise pool sqlGenCtx logger httpManager
|
2019-01-02 14:24:17 +03:00
|
|
|
|
2019-09-09 23:26:04 +03:00
|
|
|
HasuraApp app cacheRef cacheInitTime shutdownApp <-
|
2019-05-16 09:13:25 +03:00
|
|
|
mkWaiApp isoL loggerCtx sqlGenCtx enableAL pool ci httpManager am
|
2019-05-16 10:45:29 +03:00
|
|
|
corsCfg enableConsole consoleAssetsDir enableTelemetry
|
|
|
|
instanceId enabledAPIs lqOpts
|
2019-03-12 08:46:27 +03:00
|
|
|
|
2019-04-17 19:29:39 +03:00
|
|
|
-- log inconsistent schema objects
|
2019-04-29 09:22:48 +03:00
|
|
|
inconsObjs <- scInconsistentObjs <$> getSCFromRef cacheRef
|
|
|
|
logInconsObjs logger inconsObjs
|
2019-04-17 19:29:39 +03:00
|
|
|
|
2019-03-12 08:46:27 +03:00
|
|
|
-- start a background thread for schema sync
|
2019-04-17 19:29:39 +03:00
|
|
|
startSchemaSync sqlGenCtx pool logger httpManager
|
2019-03-12 08:46:27 +03:00
|
|
|
cacheRef instanceId cacheInitTime
|
2019-01-11 14:07:13 +03:00
|
|
|
|
2019-08-26 08:31:27 +03:00
|
|
|
let warpSettings = Warp.setPort port
|
|
|
|
. Warp.setHost host
|
|
|
|
. Warp.setGracefulShutdownTimeout (Just 30) -- 30s graceful shutdown
|
2019-09-09 23:26:04 +03:00
|
|
|
. Warp.setInstallShutdownHandler (shutdownHandler logger shutdownApp)
|
2019-08-26 08:31:27 +03:00
|
|
|
$ Warp.defaultSettings
|
2018-07-27 12:34:50 +03:00
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
maxEvThrds <- getFromEnv defaultMaxEventThreads "HASURA_GRAPHQL_EVENTS_HTTP_POOL_SIZE"
|
2018-10-30 18:20:18 +03:00
|
|
|
evFetchMilliSec <- getFromEnv defaultFetchIntervalMilliSec "HASURA_GRAPHQL_EVENTS_FETCH_INTERVAL"
|
2018-10-26 19:28:03 +03:00
|
|
|
logEnvHeaders <- getFromEnv False "LOG_HEADERS_FROM_ENV"
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2019-05-08 10:36:43 +03:00
|
|
|
-- prepare event triggers data
|
|
|
|
prepareEvents pool logger
|
2018-10-30 18:20:18 +03:00
|
|
|
eventEngineCtx <- atomically $ initEventEngineCtx maxEvThrds evFetchMilliSec
|
2019-03-12 08:46:27 +03:00
|
|
|
let scRef = _scrCache cacheRef
|
2019-01-02 14:24:17 +03:00
|
|
|
unLogger logger $
|
2019-07-11 08:37:06 +03:00
|
|
|
mkGenericStrLog LevelInfo "event_triggers" "starting workers"
|
2019-04-17 12:48:41 +03:00
|
|
|
void $ C.forkIO $ processEventQueue hloggerCtx logEnvHeaders
|
|
|
|
httpManager pool scRef eventEngineCtx
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2019-01-28 16:55:28 +03:00
|
|
|
-- start a background thread to check for updates
|
|
|
|
void $ C.forkIO $ checkForUpdates loggerCtx httpManager
|
|
|
|
|
|
|
|
-- start a background thread for telemetry
|
|
|
|
when enableTelemetry $ do
|
2019-07-11 08:37:06 +03:00
|
|
|
unLogger logger $ mkGenericStrLog LevelInfo "telemetry" telemetryNotice
|
2019-07-31 12:01:48 +03:00
|
|
|
void $ C.forkIO $ runTelemetry logger httpManager scRef dbId instanceId
|
2019-01-28 16:55:28 +03:00
|
|
|
|
2019-05-08 10:36:43 +03:00
|
|
|
finishTime <- Clock.getCurrentTime
|
|
|
|
let apiInitTime = realToFrac $ Clock.diffUTCTime finishTime initTime
|
2019-07-11 08:37:06 +03:00
|
|
|
unLogger logger $ mkGenericLog LevelInfo "server" $
|
|
|
|
StartupTimeInfo "starting API server" apiInitTime
|
2018-07-20 10:22:46 +03:00
|
|
|
Warp.runSettings warpSettings app
|
2018-07-27 12:34:50 +03:00
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
HCExport -> do
|
2019-07-11 08:37:06 +03:00
|
|
|
(_, _, pgLogger) <- mkLoggers defaultEnabledLogTypes LevelInfo
|
2018-12-19 14:38:33 +03:00
|
|
|
ci <- procConnInfo rci
|
2019-05-08 10:36:43 +03:00
|
|
|
res <- runTx' pgLogger ci fetchMetadata
|
2018-12-19 14:38:33 +03:00
|
|
|
either printErrJExit printJSON res
|
2019-01-02 14:24:17 +03:00
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
HCClean -> do
|
2019-07-11 08:37:06 +03:00
|
|
|
(_, _, pgLogger) <- mkLoggers defaultEnabledLogTypes LevelInfo
|
2018-12-19 14:38:33 +03:00
|
|
|
ci <- procConnInfo rci
|
2019-05-08 10:36:43 +03:00
|
|
|
res <- runTx' pgLogger ci cleanCatalog
|
2018-12-19 14:38:33 +03:00
|
|
|
either printErrJExit (const cleanSuccess) res
|
2019-01-02 14:24:17 +03:00
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
HCExecute -> do
|
2019-07-11 08:37:06 +03:00
|
|
|
(_, _, pgLogger) <- mkLoggers defaultEnabledLogTypes LevelInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
queryBs <- BL.getContents
|
2018-12-19 14:38:33 +03:00
|
|
|
ci <- procConnInfo rci
|
2019-04-17 19:29:39 +03:00
|
|
|
let sqlGenCtx = SQLGenCtx False
|
2019-05-08 10:36:43 +03:00
|
|
|
pool <- getMinimalPool pgLogger ci
|
|
|
|
res <- runAsAdmin pool sqlGenCtx httpManager $ execQuery queryBs
|
2018-12-19 14:38:33 +03:00
|
|
|
either printErrJExit BLC.putStrLn res
|
2019-01-02 14:24:17 +03:00
|
|
|
|
2018-12-19 14:38:33 +03:00
|
|
|
HCVersion -> putStrLn $ "Hasura GraphQL Engine: " ++ T.unpack currentVersion
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2019-01-28 16:55:28 +03:00
|
|
|
|
2019-07-11 08:37:06 +03:00
|
|
|
mkLoggers enabledLogs logLevel = do
|
|
|
|
loggerCtx <- mkLoggerCtx (defaultLoggerSettings True logLevel) enabledLogs
|
|
|
|
let logger = mkLogger loggerCtx
|
|
|
|
pgLogger = mkPGLogger logger
|
|
|
|
return (loggerCtx, logger, pgLogger)
|
|
|
|
|
2019-05-08 10:36:43 +03:00
|
|
|
runTx pool tx =
|
2018-06-27 16:11:32 +03:00
|
|
|
runExceptT $ Q.runTx pool (Q.Serializable, Nothing) tx
|
2018-12-13 10:26:15 +03:00
|
|
|
|
2019-05-08 10:36:43 +03:00
|
|
|
runTx' pgLogger ci tx = do
|
2019-03-12 08:46:27 +03:00
|
|
|
pool <- getMinimalPool pgLogger ci
|
2019-05-08 10:36:43 +03:00
|
|
|
runExceptT $ Q.runTx pool (Q.Serializable, Nothing) tx
|
|
|
|
|
|
|
|
runAsAdmin pool sqlGenCtx httpManager m = do
|
2018-12-13 10:26:15 +03:00
|
|
|
res <- runExceptT $ peelRun emptySchemaCache adminUserInfo
|
2019-04-17 19:29:39 +03:00
|
|
|
httpManager sqlGenCtx (PGExecCtx pool Q.Serializable) m
|
2018-12-13 10:26:15 +03:00
|
|
|
return $ fmap fst res
|
2019-01-02 14:24:17 +03:00
|
|
|
|
|
|
|
procConnInfo rci =
|
|
|
|
either (printErrExit . connInfoErrModifier) return $
|
|
|
|
mkConnInfo rci
|
|
|
|
|
2019-03-12 08:46:27 +03:00
|
|
|
getMinimalPool pgLogger ci = do
|
2018-06-27 16:11:32 +03:00
|
|
|
let connParams = Q.defaultConnParams { Q.cpConns = 1 }
|
2019-03-12 08:46:27 +03:00
|
|
|
Q.initPGPool ci connParams pgLogger
|
2019-01-02 14:24:17 +03:00
|
|
|
|
2019-05-08 10:36:43 +03:00
|
|
|
initialise pool sqlGenCtx (Logger logger) httpMgr = do
|
2018-06-27 16:11:32 +03:00
|
|
|
currentTime <- getCurrentTime
|
2019-01-28 16:55:28 +03:00
|
|
|
-- initialise the catalog
|
2019-05-08 10:36:43 +03:00
|
|
|
initRes <- runAsAdmin pool sqlGenCtx httpMgr $
|
|
|
|
initCatalogSafe currentTime
|
2019-07-11 08:37:06 +03:00
|
|
|
either printErrJExit (logger . mkGenericStrLog LevelInfo "db_init") initRes
|
2019-01-28 16:55:28 +03:00
|
|
|
|
|
|
|
-- migrate catalog if necessary
|
2019-05-08 10:36:43 +03:00
|
|
|
migRes <- runAsAdmin pool sqlGenCtx httpMgr $
|
|
|
|
migrateCatalog currentTime
|
2019-07-11 08:37:06 +03:00
|
|
|
either printErrJExit (logger . mkGenericStrLog LevelInfo "db_migrate") migRes
|
2019-01-28 16:55:28 +03:00
|
|
|
|
2019-07-31 12:01:48 +03:00
|
|
|
-- retrieve database id
|
|
|
|
eDbId <- runTx pool getDbId
|
|
|
|
either printErrJExit return eDbId
|
2019-01-02 14:24:17 +03:00
|
|
|
|
2019-05-08 10:36:43 +03:00
|
|
|
prepareEvents pool (Logger logger) = do
|
2019-07-11 08:37:06 +03:00
|
|
|
logger $ mkGenericStrLog LevelInfo "event_triggers" "preparing data"
|
2019-05-08 10:36:43 +03:00
|
|
|
res <- runTx pool unlockAllEvents
|
2018-12-19 14:38:33 +03:00
|
|
|
either printErrJExit return res
|
2018-11-15 07:55:39 +03:00
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
getFromEnv :: (Read a) => a -> String -> IO a
|
|
|
|
getFromEnv defaults env = do
|
|
|
|
mEnv <- lookupEnv env
|
|
|
|
let mRes = case mEnv of
|
|
|
|
Nothing -> Just defaults
|
|
|
|
Just val -> readMaybe val
|
2018-10-26 19:28:03 +03:00
|
|
|
eRes = maybe (Left $ "Wrong expected type for environment variable: " <> env) Right mRes
|
2018-12-19 14:38:33 +03:00
|
|
|
either printErrExit return eRes
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-01-02 14:24:17 +03:00
|
|
|
cleanSuccess =
|
|
|
|
putStrLn "successfully cleaned graphql-engine related data"
|
2019-01-28 16:55:28 +03:00
|
|
|
|
2019-08-26 08:31:27 +03:00
|
|
|
-- | Catches the SIGTERM signal and initiates a graceful shutdown. Graceful shutdown for regular HTTP
|
|
|
|
-- requests is already implemented in Warp, and is triggered by invoking the 'closeSocket' callback.
|
|
|
|
-- We only catch the SIGTERM signal once, that is, if the user hits CTRL-C once again, we terminate
|
|
|
|
-- the process immediately.
|
2019-09-09 23:26:04 +03:00
|
|
|
shutdownHandler :: Logger -> IO () -> IO () -> IO ()
|
|
|
|
shutdownHandler (Logger logger) shutdownApp closeSocket =
|
|
|
|
void $ Signals.installHandler
|
|
|
|
Signals.sigTERM
|
|
|
|
(Signals.CatchOnce shutdownSequence)
|
|
|
|
Nothing
|
2019-08-26 08:31:27 +03:00
|
|
|
where
|
2019-09-09 23:26:04 +03:00
|
|
|
shutdownSequence = do
|
|
|
|
closeSocket
|
|
|
|
shutdownApp
|
|
|
|
logShutdown
|
|
|
|
|
2019-08-26 08:31:27 +03:00
|
|
|
logShutdown = logger $
|
|
|
|
mkGenericStrLog LevelInfo "server" "gracefully shutting down server"
|
2019-01-28 16:55:28 +03:00
|
|
|
|
|
|
|
telemetryNotice :: String
|
|
|
|
telemetryNotice =
|
|
|
|
"Help us improve Hasura! The graphql-engine server collects anonymized "
|
|
|
|
<> "usage stats which allows us to keep improving Hasura at warp speed. "
|
|
|
|
<> "To read more or opt-out, visit https://docs.hasura.io/1.0/graphql/manual/guides/telemetry.html"
|