diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-02-12 00:54:43 +0000 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-02-12 00:54:43 +0000 |
| commit | f4aa09d615a9cb77f1d13cbbc516be23a2d3cc69 (patch) | |
| tree | 5161dd00d07b976864d800bc5dbd3ae560498141 | |
| parent | 6e89aaceb65815380f31674801dfebc084737ea2 (diff) | |
| download | thermoprint-f4aa09d615a9cb77f1d13cbbc516be23a2d3cc69.tar thermoprint-f4aa09d615a9cb77f1d13cbbc516be23a2d3cc69.tar.gz thermoprint-f4aa09d615a9cb77f1d13cbbc516be23a2d3cc69.tar.bz2 thermoprint-f4aa09d615a9cb77f1d13cbbc516be23a2d3cc69.tar.xz thermoprint-f4aa09d615a9cb77f1d13cbbc516be23a2d3cc69.zip | |
Prototype queue manager configuration
| -rw-r--r-- | server/default-conf/Main.hs | 2 | ||||
| -rw-r--r-- | server/src/Thermoprint/Server.hs | 71 |
2 files changed, 52 insertions, 21 deletions
diff --git a/server/default-conf/Main.hs b/server/default-conf/Main.hs index 39e500d..36f6c12 100644 --- a/server/default-conf/Main.hs +++ b/server/default-conf/Main.hs | |||
| @@ -19,5 +19,5 @@ main = thermoprintServer (Nat runSqlite) $ def `withPrinters` printers | |||
| 19 | runSqlite :: ReaderT ConnectionPool (LoggingT IO) a -> IO a | 19 | runSqlite :: ReaderT ConnectionPool (LoggingT IO) a -> IO a |
| 20 | runSqlite = runStderrLoggingT . withSqlitePool "thermoprint.sqlite" 1 . runReaderT | 20 | runSqlite = runStderrLoggingT . withSqlitePool "thermoprint.sqlite" 1 . runReaderT |
| 21 | 21 | ||
| 22 | printers = [ pure debugPrint | 22 | printers = [ (pure debugPrint, def) |
| 23 | ] | 23 | ] |
diff --git a/server/src/Thermoprint/Server.hs b/server/src/Thermoprint/Server.hs index 2dcb8e9..2413b2a 100644 --- a/server/src/Thermoprint/Server.hs +++ b/server/src/Thermoprint/Server.hs | |||
| @@ -1,13 +1,15 @@ | |||
| 1 | {-# LANGUAGE RecordWildCards #-} | 1 | {-# LANGUAGE RecordWildCards #-} |
| 2 | {-# LANGUAGE TemplateHaskell #-} | 2 | {-# LANGUAGE TemplateHaskell #-} |
| 3 | {-# LANGUAGE OverloadedStrings #-} | 3 | {-# LANGUAGE OverloadedStrings #-} |
| 4 | {-# LANGUAGE TypeOperators #-} | 4 | {-# LANGUAGE TypeOperators #-} |
| 5 | {-# LANGUAGE FlexibleContexts #-} | 5 | {-# LANGUAGE FlexibleContexts #-} |
| 6 | {-# LANGUAGE ImpredicativeTypes #-} | 6 | {-# LANGUAGE ImpredicativeTypes #-} |
| 7 | {-# LANGUAGE ExistentialQuantification #-} | ||
| 8 | {-# LANGUAGE ViewPatterns #-} | ||
| 7 | 9 | ||
| 8 | module Thermoprint.Server | 10 | module Thermoprint.Server |
| 9 | ( thermoprintServer | 11 | ( thermoprintServer |
| 10 | , Config(..) | 12 | , Config(..), QMConfig(..) |
| 11 | , withPrinters | 13 | , withPrinters |
| 12 | , module Data.Default.Class | 14 | , module Data.Default.Class |
| 13 | , module Servant.Server.Internal.Enter | 15 | , module Servant.Server.Internal.Enter |
| @@ -26,13 +28,18 @@ import Data.Foldable (mapM_, forM_, foldlM) | |||
| 26 | 28 | ||
| 27 | import Control.Monad.Trans.Resource | 29 | import Control.Monad.Trans.Resource |
| 28 | import Control.Monad.Trans.Control | 30 | import Control.Monad.Trans.Control |
| 31 | import Control.Monad.Trans.Identity | ||
| 29 | import Control.Monad.Logger | 32 | import Control.Monad.Logger |
| 30 | import Control.Monad.Reader | 33 | import Control.Monad.Reader |
| 31 | import Control.Monad.IO.Class | 34 | import Control.Monad.IO.Class |
| 35 | import Control.Monad.Morph | ||
| 32 | import Control.Category | 36 | import Control.Category |
| 33 | import Prelude hiding (id, (.)) | 37 | import Prelude hiding (id, (.)) |
| 34 | 38 | ||
| 39 | import qualified Control.Monad as M | ||
| 40 | |||
| 35 | import Control.Concurrent | 41 | import Control.Concurrent |
| 42 | import Control.Concurrent.STM | ||
| 36 | 43 | ||
| 37 | import Data.Text (Text) | 44 | import Data.Text (Text) |
| 38 | import qualified Data.Text as T (pack) | 45 | import qualified Data.Text as T (pack) |
| @@ -55,21 +62,42 @@ import qualified Thermoprint.Server.API as API (thermoprintServer) | |||
| 55 | import Thermoprint.Server.API hiding (thermoprintServer) | 62 | import Thermoprint.Server.API hiding (thermoprintServer) |
| 56 | 63 | ||
| 57 | -- | Compile-time configuration for 'thermoprintServer' | 64 | -- | Compile-time configuration for 'thermoprintServer' |
| 58 | data Config = Config { dyreError :: Maybe String -- ^ Set by 'Dyre' -- sent to log as an error | 65 | data Config m = Config { dyreError :: Maybe String -- ^ Set by 'Dyre' -- sent to log as an error |
| 59 | , warpSettings :: Warp.Settings -- ^ Configure 'Warp's behaviour | 66 | , warpSettings :: Warp.Settings -- ^ Configure 'Warp's behaviour |
| 60 | , printers :: Map PrinterId Printer | 67 | , printers :: Map PrinterId Printer |
| 61 | } | 68 | , queueManagers :: PrinterId -> QMConfig m |
| 62 | 69 | } | |
| 63 | instance Default Config where | 70 | |
| 64 | def = Config { dyreError = Nothing | 71 | data QMConfig m = forall t. ( MonadTrans t |
| 65 | , warpSettings = Warp.defaultSettings | 72 | , MFunctor t |
| 66 | , printers = Map.empty | 73 | , Monad (t STM) |
| 74 | , MonadIO (t IO) | ||
| 75 | ) => QMConfig { manager :: QueueManager t | ||
| 76 | , collapse :: (t IO) :~> m | ||
| 77 | } | ||
| 78 | |||
| 79 | instance MonadIO m => Default (Config m) where | ||
| 80 | def = Config { dyreError = Nothing | ||
| 81 | , warpSettings = Warp.defaultSettings | ||
| 82 | , printers = Map.empty | ||
| 83 | , queueManagers = const def | ||
| 67 | } | 84 | } |
| 68 | 85 | ||
| 69 | withPrinters :: MonadResource m => Config -> [m PrinterMethod] -> m Config | 86 | instance MonadIO m => Default (QMConfig m) where |
| 87 | def = QMConfig idQM $ Nat (liftIO . runIdentityT) | ||
| 88 | |||
| 89 | withPrinters :: MonadResource m => Config m -> [(m PrinterMethod, QMConfig m)] -> m (Config m) | ||
| 70 | -- ^ Add a list of printers to a 'Config' | 90 | -- ^ Add a list of printers to a 'Config' |
| 71 | withPrinters cfg pss = (\map -> cfg { printers = map }) <$> foldlM (\map spec -> Map.insert (nextKey map) <$> printer spec <*> pure map) Map.empty pss | 91 | withPrinters cfg = fmap updateCfg . foldlM mapInsert (Map.mapWithKey (\k a -> (a, queueManagers cfg k)) $ printers cfg) |
| 72 | where | 92 | where |
| 93 | mapInsert map (spec, qm) = Map.insert (nextKey map) <$> ((,) <$> printer spec <*> pure qm) <*> pure map | ||
| 94 | updateCfg map = let | ||
| 95 | printerMap = fmap fst map | ||
| 96 | qmMap = fmap snd map | ||
| 97 | qmMap' id | ||
| 98 | | (Just qm) <- (Map.lookup id qmMap) = qm | ||
| 99 | | otherwise = queueManagers cfg id | ||
| 100 | in cfg { printers = printerMap, queueManagers = qmMap' } | ||
| 73 | nextKey map | 101 | nextKey map |
| 74 | | Map.null map = 0 | 102 | | Map.null map = 0 |
| 75 | | otherwise = succ . fst $ Map.findMax map | 103 | | otherwise = succ . fst $ Map.findMax map |
| @@ -77,8 +105,8 @@ withPrinters cfg pss = (\map -> cfg { printers = map }) <$> foldlM (\map spec -> | |||
| 77 | thermoprintServer :: ( MonadLoggerIO m | 105 | thermoprintServer :: ( MonadLoggerIO m |
| 78 | , MonadReader ConnectionPool m | 106 | , MonadReader ConnectionPool m |
| 79 | , MonadResourceBase m | 107 | , MonadResourceBase m |
| 80 | ) => (m :~> IO) -- ^ 'dyre' controls the base of the monad-transformer-stack ('IO') but we let the user specify the rest of it. Therefore we require a specification of how to collapse the stack. | 108 | ) => (m :~> IO) -- ^ 'dyre' controls the base of the monad-transformer-stack ('IO') but we let the user specify much of the rest of it (we handle 'ResourceT' ourselves, since we need it to fork properly). Therefore we require a specification of how to collapse the stack. |
| 81 | -> ResourceT m Config -> IO () | 109 | -> ResourceT m (Config (ResourceT m)) -> IO () |
| 82 | -- ^ Run the server | 110 | -- ^ Run the server |
| 83 | thermoprintServer io = Dyre.wrapMain $ Dyre.defaultParams | 111 | thermoprintServer io = Dyre.wrapMain $ Dyre.defaultParams |
| 84 | { Dyre.projectName = "thermoprint-server" | 112 | { Dyre.projectName = "thermoprint-server" |
| @@ -91,4 +119,7 @@ thermoprintServer io = Dyre.wrapMain $ Dyre.defaultParams | |||
| 91 | maybe (return ()) ($(logErrorS) "Dyre" . T.pack) dyreError | 119 | maybe (return ()) ($(logErrorS) "Dyre" . T.pack) dyreError |
| 92 | mapM_ ($(logWarnS) "DB") =<< runSqlPool (runMigrationSilent migrateAll) =<< ask | 120 | mapM_ ($(logWarnS) "DB") =<< runSqlPool (runMigrationSilent migrateAll) =<< ask |
| 93 | forM_ printers $ resourceForkIO . runPrinter | 121 | forM_ printers $ resourceForkIO . runPrinter |
| 122 | let | ||
| 123 | runQM' (queueManagers -> QMConfig qm nat) printer = unNat nat $ runQM qm printer | ||
| 124 | Map.foldrWithKey (\k p a -> resourceForkIO (runQM' k p) >> a) (return ()) printers | ||
| 94 | liftIO . Warp.runSettings warpSettings . serve thermoprintAPI . flip enter API.thermoprintServer =<< handlerNat printers | 125 | liftIO . Warp.runSettings warpSettings . serve thermoprintAPI . flip enter API.thermoprintServer =<< handlerNat printers |
