2026-07-17 21:43:03 +09:00
|
|
|
module Main (main) where
|
|
|
|
|
|
|
|
|
|
import Data.String (fromString)
|
|
|
|
|
import Database.PostgreSQL.Simple (Only (..))
|
|
|
|
|
import Network.Wai.Handler.Warp
|
|
|
|
|
( HostPreference
|
|
|
|
|
, defaultSettings
|
|
|
|
|
, setHost
|
|
|
|
|
, setPort
|
|
|
|
|
)
|
2026-07-18 18:08:41 +09:00
|
|
|
import Network.Wai.Handler.WarpTLS (runTLS, tlsSettings)
|
2026-07-17 21:43:03 +09:00
|
|
|
import Nuthatch
|
|
|
|
|
import Nuthatch.Db (migrate, query_, withDb)
|
2026-07-19 18:22:33 +09:00
|
|
|
import Nuthatch.Mutation.Recovery (runRecovery)
|
2026-07-17 21:43:03 +09:00
|
|
|
import Nuthatch.Redis (withRedis)
|
2026-07-18 22:49:19 +09:00
|
|
|
import Nuthatch.Recovery (withLinkedWorker)
|
2026-07-19 03:41:01 +09:00
|
|
|
import Nuthatch.Runtime (retryStartup)
|
2026-07-17 21:43:03 +09:00
|
|
|
import Nuthatch.S3 (newS3)
|
2026-07-18 15:22:57 +09:00
|
|
|
import System.Directory (doesDirectoryExist)
|
2026-07-17 21:43:03 +09:00
|
|
|
import System.FilePath ((</>))
|
|
|
|
|
import System.IO (BufferMode (LineBuffering), hSetBuffering, stdout)
|
|
|
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
|
main = do
|
|
|
|
|
hSetBuffering stdout LineBuffering
|
|
|
|
|
cfg <- loadConfig
|
2026-07-20 02:21:33 +09:00
|
|
|
let runtimeCfg = cfgRuntime cfg
|
|
|
|
|
httpCfg = cfgHttp cfg
|
|
|
|
|
postgresCfg = cfgPostgres cfg
|
|
|
|
|
redisCfg = cfgRedis cfg
|
|
|
|
|
s3Cfg = cfgS3 cfg
|
|
|
|
|
productCfg = cfgProduct cfg
|
2026-07-19 03:41:01 +09:00
|
|
|
retryStartup
|
2026-07-20 02:21:33 +09:00
|
|
|
(cfgStartupAttempts runtimeCfg)
|
|
|
|
|
(cfgStartupDelayMs runtimeCfg)
|
2026-07-19 03:41:01 +09:00
|
|
|
"postgresql"
|
2026-07-20 02:21:33 +09:00
|
|
|
(withDb postgresCfg $ \db -> do
|
2026-07-19 03:41:01 +09:00
|
|
|
_ <- query_ db "SELECT 1" :: IO [Only Int]
|
|
|
|
|
pure ())
|
2026-07-20 02:21:33 +09:00
|
|
|
withDb postgresCfg $ \db -> do
|
2026-07-17 21:43:03 +09:00
|
|
|
schemaPath <- findSchema
|
2026-07-19 03:41:01 +09:00
|
|
|
retryStartup
|
2026-07-20 02:21:33 +09:00
|
|
|
(cfgStartupAttempts runtimeCfg)
|
|
|
|
|
(cfgStartupDelayMs runtimeCfg)
|
2026-07-19 03:41:01 +09:00
|
|
|
"migration"
|
2026-07-20 02:21:33 +09:00
|
|
|
(migrate db schemaPath productCfg)
|
|
|
|
|
withRedis redisCfg $ \redis -> do
|
|
|
|
|
s3 <- newS3 s3Cfg
|
2026-07-17 21:43:03 +09:00
|
|
|
let env = newEnv cfg db redis s3
|
2026-07-18 22:49:19 +09:00
|
|
|
withLinkedWorker (runRecovery env) $ do
|
|
|
|
|
let settings =
|
2026-07-20 02:21:33 +09:00
|
|
|
setPort (cfgListenPort httpCfg) $
|
|
|
|
|
setHost (readHost (cfgListenHost httpCfg)) defaultSettings
|
2026-07-18 22:49:19 +09:00
|
|
|
putStrLn $
|
|
|
|
|
"nuthatch listening on "
|
2026-07-20 02:21:33 +09:00
|
|
|
<> cfgListenHost httpCfg
|
2026-07-18 22:49:19 +09:00
|
|
|
<> ":"
|
2026-07-20 02:21:33 +09:00
|
|
|
<> show (cfgListenPort httpCfg)
|
2026-07-18 22:49:19 +09:00
|
|
|
runTLS
|
2026-07-20 02:21:33 +09:00
|
|
|
(tlsSettings (cfgTlsCertPath httpCfg) (cfgTlsKeyPath httpCfg))
|
2026-07-18 22:49:19 +09:00
|
|
|
settings
|
|
|
|
|
(application env)
|
2026-07-17 21:43:03 +09:00
|
|
|
|
|
|
|
|
findSchema :: IO FilePath
|
|
|
|
|
findSchema = do
|
|
|
|
|
let candidates =
|
2026-07-18 15:22:57 +09:00
|
|
|
[ "sql"
|
|
|
|
|
, ".." </> "sql"
|
|
|
|
|
, "/app/sql"
|
2026-07-17 21:43:03 +09:00
|
|
|
]
|
2026-07-18 15:22:57 +09:00
|
|
|
existing <- mapM (\p -> doesDirectoryExist p >>= \e -> pure (e, p)) candidates
|
2026-07-17 21:43:03 +09:00
|
|
|
pure $ case [p | (True, p) <- existing] of
|
|
|
|
|
(p : _) -> p
|
2026-07-18 15:22:57 +09:00
|
|
|
[] -> "sql"
|
2026-07-17 21:43:03 +09:00
|
|
|
|
|
|
|
|
readHost :: String -> HostPreference
|
|
|
|
|
readHost = fromString
|