stackage-server/Application.hs

135 lines
4.8 KiB
Haskell
Raw Normal View History

2014-04-09 07:52:04 +00:00
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Application
( makeApplication
, getApplicationDev
, makeFoundation
) where
import Import
import Settings
import Yesod.Default.Config
import Yesod.Default.Main
import Yesod.Default.Handlers
import Network.Wai.Middleware.RequestLogger
( mkRequestLogger, outputFormat, OutputFormat (..), IPAddrSource (..), destination
)
import qualified Network.Wai.Middleware.RequestLogger as RequestLogger
import qualified Database.Persist
import Control.Monad.Logger (runLoggingT)
import Control.Monad.Reader (runReaderT)
2014-04-09 07:52:04 +00:00
import Control.Concurrent (forkIO, threadDelay)
import System.Log.FastLogger (newStdoutLoggerSet, defaultBufSize, flushLogStr)
2014-04-09 07:52:04 +00:00
import Network.Wai.Logger (clockDateCacher)
import Yesod.Core.Types (loggerSet, Logger (Logger))
2014-04-09 11:38:54 +00:00
import qualified System.Random.MWC as MWC
import qualified Network.Wai as Wai
import Network.Wai.Middleware.MethodOverride (methodOverride)
import Data.BlobStore (fileStore)
import Data.Hackage
2014-04-09 07:52:04 +00:00
-- Import all relevant handler modules here.
-- Don't forget to add new modules to your cabal file!
import Handler.Home
2014-04-09 11:38:54 +00:00
import Handler.Profile
import Handler.Email
import Handler.ResetToken
import Handler.HackageSdist
2014-04-10 09:46:37 +00:00
import Handler.UploadStackage
2014-04-09 07:52:04 +00:00
-- This line actually creates our YesodDispatch instance. It is the second half
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
-- comments there for more details.
mkYesodDispatch "App" resourcesApp
-- This function allocates resources (such as a database connection pool),
-- performs initialization and creates a WAI application. This is also the
-- place to put your migrate statements to have automatic database
-- migrations handled by Yesod.
makeApplication :: AppConfig DefaultEnv Extra -> IO (Application, LogFunc)
makeApplication conf = do
foundation <- makeFoundation conf
-- Initialize the logging middleware
logWare <- mkRequestLogger def
{ outputFormat =
if development
then Detailed True
else Apache FromSocket
, destination = RequestLogger.Logger $ loggerSet $ appLogger foundation
}
-- Create the WAI application and apply middlewares
app <- toWaiAppPlain foundation
let logFunc = messageLoggerSource foundation (appLogger foundation)
2014-04-09 11:38:54 +00:00
middleware = logWare . defaultWAIMiddleware
return (middleware app, logFunc)
defaultWAIMiddleware :: Wai.Middleware -- FIXME move upstream
defaultWAIMiddleware = methodOverride
2014-04-09 07:52:04 +00:00
-- | Loads up any necessary settings, creates your foundation datatype, and
-- performs some initialization.
makeFoundation :: AppConfig DefaultEnv Extra -> IO App
makeFoundation conf = do
manager <- newManager
s <- staticSite
dbconf <- withYamlEnvironment "config/postgresql.yml" (appEnv conf)
Database.Persist.loadConfig >>=
Database.Persist.applyEnv
p <- Database.Persist.createPoolConfig (dbconf :: Settings.PersistConf)
loggerSet' <- newStdoutLoggerSet defaultBufSize
(getter, updater) <- clockDateCacher
-- If the Yesod logger (as opposed to the request logger middleware) is
-- used less than once a second on average, you may prefer to omit this
-- thread and use "(updater >> getter)" in place of "getter" below. That
-- would update the cache every time it is used, instead of every second.
let updateLoop = do
threadDelay 1000000
updater
flushLogStr loggerSet' -- FIXME include upstream!
2014-04-09 07:52:04 +00:00
updateLoop
_ <- forkIO updateLoop
2014-04-09 11:38:54 +00:00
gen <- MWC.createSystemRandom
2014-04-09 07:52:04 +00:00
let logger = Yesod.Core.Types.Logger loggerSet' getter
2014-04-09 11:38:54 +00:00
foundation = App
{ settings = conf
, getStatic = s
, connPool = p
, httpManager = manager
, persistConfig = dbconf
, appLogger = logger
, genIO = gen
, blobStore =
case storeConfig $ appExtra conf of
BSCFile root -> fileStore root
2014-04-09 11:38:54 +00:00
}
2014-04-09 07:52:04 +00:00
-- Perform database migration using our application's logging settings.
runLoggingT
(Database.Persist.runPool dbconf (runMigration migrateAll) p)
(messageLoggerSource foundation logger)
-- Start the cabal file loader
void $ forkIO $ forever $ flip runLoggingT (messageLoggerSource foundation logger) $ do
when development $ liftIO $ threadDelay $ 5 * 60 * 1000000
eres <- tryAny $ runReaderT loadCabalFiles foundation
case eres of
Left e -> $logError $ tshow e
Right () -> return ()
liftIO $ threadDelay $ 30 * 60 * 1000000
2014-04-09 07:52:04 +00:00
return foundation
-- for yesod devel
getApplicationDev :: IO (Int, Application)
getApplicationDev =
defaultDevelApp loader (fmap fst . makeApplication)
where
loader = Yesod.Default.Config.loadConfig (configSettings Development)
{ csParseExtra = parseExtra
}