nuthatch/app/Main.hs

77 lines
2.4 KiB
Haskell
Raw Permalink Normal View History

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