diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-02-29 22:14:57 +0100 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-02-29 22:14:57 +0100 |
commit | d07c1cf5d04f802501a98ce986b78d42b7329901 (patch) | |
tree | feac0da36aed47723c3a7b75ad9df24eb5103007 /server | |
parent | 844f5e96097f8fcced94220487a7c5ad40c1e97f (diff) | |
download | thermoprint-d07c1cf5d04f802501a98ce986b78d42b7329901.tar thermoprint-d07c1cf5d04f802501a98ce986b78d42b7329901.tar.gz thermoprint-d07c1cf5d04f802501a98ce986b78d42b7329901.tar.bz2 thermoprint-d07c1cf5d04f802501a98ce986b78d42b7329901.tar.xz thermoprint-d07c1cf5d04f802501a98ce986b78d42b7329901.zip |
Further work on QMConfig tools
Diffstat (limited to 'server')
-rw-r--r-- | server/src/Thermoprint/Server.hs | 6 | ||||
-rw-r--r-- | server/src/Thermoprint/Server/QMConfig.hs | 92 | ||||
-rw-r--r-- | server/thermoprint-server.cabal | 1 | ||||
-rw-r--r-- | server/thermoprint-server.nix | 19 |
4 files changed, 69 insertions, 49 deletions
diff --git a/server/src/Thermoprint/Server.hs b/server/src/Thermoprint/Server.hs index 49f3e82..c2a4972 100644 --- a/server/src/Thermoprint/Server.hs +++ b/server/src/Thermoprint/Server.hs | |||
@@ -89,7 +89,7 @@ import Debug.Trace | |||
89 | data Config m = Config { dyreError :: Maybe String -- ^ Set by 'Dyre' -- sent to log as an error | 89 | data Config m = Config { dyreError :: Maybe String -- ^ Set by 'Dyre' -- sent to log as an error |
90 | , warpSettings :: Warp.Settings -- ^ Configure 'Warp's behaviour | 90 | , warpSettings :: Warp.Settings -- ^ Configure 'Warp's behaviour |
91 | , printers :: Map API.PrinterId Printer | 91 | , printers :: Map API.PrinterId Printer |
92 | , queueManagers :: API.PrinterId -> QMConfig m | 92 | , queueManagers :: API.PrinterId -> QMConfig |
93 | } | 93 | } |
94 | 94 | ||
95 | instance MonadIO m => Default (Config m) where | 95 | instance MonadIO m => Default (Config m) where |
@@ -99,7 +99,7 @@ instance MonadIO m => Default (Config m) where | |||
99 | , queueManagers = const def | 99 | , queueManagers = const def |
100 | } | 100 | } |
101 | 101 | ||
102 | withPrinters :: MonadResource m => Config m -> [(m PrinterMethod, QMConfig m)] -> m (Config m) | 102 | withPrinters :: MonadResource m => Config m -> [(m PrinterMethod, QMConfig)] -> m (Config m) |
103 | -- ^ Add a list of printers to a 'Config' | 103 | -- ^ Add a list of printers to a 'Config' |
104 | withPrinters cfg = fmap updateCfg . foldlM mapInsert (Map.mapWithKey (\k a -> (a, queueManagers cfg k)) $ printers cfg) | 104 | withPrinters cfg = fmap updateCfg . foldlM mapInsert (Map.mapWithKey (\k a -> (a, queueManagers cfg k)) $ printers cfg) |
105 | where | 105 | where |
@@ -140,7 +140,7 @@ thermoprintServer dyre io = Dyre.wrapMain $ Dyre.defaultParams | |||
140 | gcChan <- liftIO newTChanIO | 140 | gcChan <- liftIO newTChanIO |
141 | fork tMgr $ jobGC gcChan | 141 | fork tMgr $ jobGC gcChan |
142 | let | 142 | let |
143 | runQM' = runQM gcChan . queueManagers | 143 | runQM' = liftIO . runQM gcChan . queueManagers |
144 | mapM_ (fork tMgr . uncurry runQM') $ Map.toList printers | 144 | mapM_ (fork tMgr . uncurry runQM') $ Map.toList printers |
145 | nChan <- liftIO $ newBroadcastTChanIO | 145 | nChan <- liftIO $ newBroadcastTChanIO |
146 | let | 146 | let |
diff --git a/server/src/Thermoprint/Server/QMConfig.hs b/server/src/Thermoprint/Server/QMConfig.hs index 8f08faf..7255c8c 100644 --- a/server/src/Thermoprint/Server/QMConfig.hs +++ b/server/src/Thermoprint/Server/QMConfig.hs | |||
@@ -4,6 +4,12 @@ | |||
4 | {-# LANGUAGE TypeOperators #-} | 4 | {-# LANGUAGE TypeOperators #-} |
5 | {-# LANGUAGE RecordWildCards #-} | 5 | {-# LANGUAGE RecordWildCards #-} |
6 | {-# LANGUAGE ViewPatterns #-} | 6 | {-# LANGUAGE ViewPatterns #-} |
7 | {-# LANGUAGE ConstraintKinds #-} | ||
8 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
9 | {-# LANGUAGE KindSignatures #-} | ||
10 | {-# LANGUAGE FlexibleInstances #-} | ||
11 | {-# LANGUAGE UndecidableInstances #-} | ||
12 | {-# LANGUAGE IncoherentInstances #-} | ||
7 | 13 | ||
8 | module Thermoprint.Server.QMConfig | 14 | module Thermoprint.Server.QMConfig |
9 | ( QMConfig(..) | 15 | ( QMConfig(..) |
@@ -21,9 +27,13 @@ import Control.Monad.Logger | |||
21 | import Control.Monad.Reader | 27 | import Control.Monad.Reader |
22 | import Control.Monad.IO.Class | 28 | import Control.Monad.IO.Class |
23 | import Control.Monad.Morph | 29 | import Control.Monad.Morph |
30 | import Control.Monad.Trans.Compose | ||
24 | import Control.Monad.State | 31 | import Control.Monad.State |
25 | import Control.Category | 32 | import Control.Category |
26 | import Servant.Server.Internal.Enter (enter, (:~>)(..)) | 33 | import Servant.Server.Internal.Enter |
34 | |||
35 | import Data.Constraint | ||
36 | import Data.Constraint.Forall | ||
27 | 37 | ||
28 | import Data.Default.Class | 38 | import Data.Default.Class |
29 | 39 | ||
@@ -37,52 +47,60 @@ import Control.Concurrent.STM | |||
37 | import Thermoprint.Server.Queue hiding (idQM, intersection, nullQM, union, runQM) | 47 | import Thermoprint.Server.Queue hiding (idQM, intersection, nullQM, union, runQM) |
38 | import qualified Thermoprint.Server.Queue as Q | 48 | import qualified Thermoprint.Server.Queue as Q |
39 | 49 | ||
50 | import Thermoprint.Server.Database (JobId) | ||
51 | |||
40 | import Prelude hiding (length, maximum, id, (.)) | 52 | import Prelude hiding (length, maximum, id, (.)) |
41 | 53 | ||
42 | data QMConfig m where | 54 | type QMTrans t = ( MonadTrans t |
43 | QMConfig :: ( MonadTrans t | 55 | , MFunctor t |
44 | , MFunctor t | 56 | , Monad (t STM) |
45 | , Monad (t STM) | 57 | , MonadIO (t IO) |
46 | , MonadIO (t IO) | 58 | , Monad (QueueManagerM t) |
47 | ) => QueueManager t -> (t IO) :~> m -> QMConfig m | 59 | , MonadState Queue (QueueManagerM t) |
48 | QMConfig' :: ( MonadIO m | 60 | ) |
49 | ) => ( forall t. ( MonadTrans t | 61 | |
50 | , MFunctor t | 62 | class QMTrans1 (t :: (* -> *) -> * -> *) (t' :: (* -> *) -> * -> *) |
51 | , Monad (t STM) | 63 | instance QMTrans (ComposeT t t') => QMTrans1 t t' |
52 | , MonadIO (t IO) | 64 | |
53 | , Monad (QueueManagerM t) | 65 | type QMTrans' t = (QMTrans t, Forall (QMTrans1 t)) |
54 | ) => QueueManager t | 66 | |
55 | ) -> QMConfig m | 67 | data QMConfig where |
56 | 68 | QMConfig :: QMTrans' t => QueueManager t -> (forall m. (t m) :~> m) -> QMConfig | |
57 | instance MonadIO m => Default (QMConfig m) where | 69 | QMConfig' :: ( forall t . QMTrans' t => QueueManager t |
70 | ) -> QMConfig | ||
71 | |||
72 | instance Default QMConfig where | ||
58 | def = idQM | 73 | def = idQM |
59 | 74 | ||
60 | intersection :: (Functor f, Foldable f, MonadIO m) => f (QMConfig m) -> QMConfig m | 75 | intersection :: Foldable f => f QMConfig -> QMConfig |
61 | intersection = foldr' (qmCombine Q.intersection) idQM | 76 | intersection = foldr' (qmCombine Q.intersection) idQM |
62 | 77 | ||
63 | idQM :: MonadIO m => QMConfig m | 78 | idQM :: QMConfig |
64 | idQM = QMConfig' Q.idQM | 79 | idQM = QMConfig' Q.idQM |
65 | 80 | ||
66 | union :: (Foldable f, MonadIO m) => f (QMConfig m) -> QMConfig m | 81 | union :: Foldable f => f QMConfig -> QMConfig |
67 | union = foldr' (qmCombine Q.union) idQM | 82 | union = foldr' (qmCombine Q.union) idQM |
68 | 83 | ||
69 | nullQM :: MonadIO m => QMConfig m | 84 | nullQM :: QMConfig |
70 | nullQM = QMConfig' Q.nullQM | 85 | nullQM = QMConfig' Q.nullQM |
71 | 86 | ||
72 | qmCombine :: ([QueueManager t] -> QueueManager t) -> QMConfig m -> QMConfig m -> QMConfig m | 87 | qmCombine :: (forall f t. (Foldable f, MonadState Queue (QueueManagerM t)) => f (QueueManager t) -> QueueManager t) -> QMConfig -> QMConfig -> QMConfig |
73 | qmCombine qmCombine' (QMConfig a natA) (QMConfig b natB) = undefined | 88 | qmCombine qmCombine' (QMConfig a natA) (QMConfig b natB) = (QMConfig (qmCombine' [a', b']) (natComp natA natB)) \\ (inst :: Forall (QMTrans1 t) :- QMTrans (ComposeT t t')) |
74 | where | 89 | where |
75 | natA :: t IO :~> m | 90 | a' = mapComposeT (hoist $ ComposeT . hoist lift) a |
76 | natB :: t' IO :~> m | 91 | b' = mapComposeT (hoist $ ComposeT . lift) b |
77 | --- | 92 | |
78 | hoistNat natB :: t (t' IO) :~> t m | 93 | natComp :: (forall m. t m :~> m) |
79 | -- | 94 | -> (forall m. t' m :~> m) |
80 | ? :: t m :~> m | 95 | -> (forall m. (MFunctor t |
81 | natAB :: ComposeT t t' IO :~> m | 96 | , Monad (t' m) |
82 | 97 | ) => ComposeT t t' m :~> m | |
83 | runQM :: ( HasQueue q ) => TChan JobId -> QMConfig m -> q -> t IO () | 98 | ) |
84 | runQM gcChan (QMConfig qm nat) q = unNat nat $ runQM gcChan qm q | 99 | natComp natA natB = natA . hoistNat natB . Nat getComposeT |
85 | runQM gcChan (QMConfig' qm) q = hoist liftIO $ runQM gcChan qm q | 100 | |
101 | runQM :: ( HasQueue q ) => TChan JobId -> QMConfig -> q -> IO () | ||
102 | runQM gcChan (QMConfig qm nat) q = unNat nat $ Q.runQM gcChan qm q | ||
103 | runQM gcChan (QMConfig' qm) q = runIdentityT $ Q.runQM gcChan qm q | ||
86 | 104 | ||
87 | standardSleep :: Monad (QueueManagerM t) => QueueManager t | 105 | standardSleep :: Monad (QueueManagerM t) => QueueManager t |
88 | -- ^ Instruct 'runQM' to sleep some standard amount of time | 106 | -- ^ Instruct 'runQM' to sleep some standard amount of time |
@@ -90,15 +108,15 @@ standardSleep :: Monad (QueueManagerM t) => QueueManager t | |||
90 | -- /TODO/: Investigate implementing a smarter algorithm (PID-controller) | 108 | -- /TODO/: Investigate implementing a smarter algorithm (PID-controller) |
91 | standardSleep = return $ 20 | 109 | standardSleep = return $ 20 |
92 | 110 | ||
93 | limitHistorySize :: MonadIO m => Int -> QMConfig m | 111 | limitHistorySize :: Int -> QMConfig |
94 | -- ^ Limit a 'Queue's 'history's size to some number of 'QueueEntry's | 112 | -- ^ Limit a 'Queue's 'history's size to some number of 'QueueEntry's |
95 | limitHistorySize max = QMConfig' $ modify' limitSize >> standardSleep | 113 | limitHistorySize max = QMConfig' $ modify' limitSize >> standardSleep |
96 | where | 114 | where |
97 | limitSize :: Queue -> Queue | 115 | limitSize :: Queue -> Queue |
98 | limitSize q@Queue{..} = q { history = Seq.take max history } | 116 | limitSize q@Queue{..} = q { history = Seq.take max history } |
99 | 117 | ||
100 | limitHistoryAge :: MonadIO m => NominalDiffTime -- ^ Maximum age relative to the youngest 'QueueEntry' | 118 | limitHistoryAge :: NominalDiffTime -- ^ Maximum age relative to the youngest 'QueueEntry' |
101 | -> QMConfig m | 119 | -> QMConfig |
102 | -- ^ Limit a 'Queue's 'history's contents to 'QueueEntry's below a certain age | 120 | -- ^ Limit a 'Queue's 'history's contents to 'QueueEntry's below a certain age |
103 | limitHistoryAge maxAge = QMConfig' $ modify' limitAge >> standardSleep | 121 | limitHistoryAge maxAge = QMConfig' $ modify' limitAge >> standardSleep |
104 | where | 122 | where |
diff --git a/server/thermoprint-server.cabal b/server/thermoprint-server.cabal index 2fa04c5..0a5690e 100644 --- a/server/thermoprint-server.cabal +++ b/server/thermoprint-server.cabal | |||
@@ -66,6 +66,7 @@ library | |||
66 | , wai-websockets >=3.0.0 && <4 | 66 | , wai-websockets >=3.0.0 && <4 |
67 | , wai >=3.0.5 && <4 | 67 | , wai >=3.0.5 && <4 |
68 | , network-uri >=2.6.0 && <3 | 68 | , network-uri >=2.6.0 && <3 |
69 | , constraints >=0.8 && <1 | ||
69 | hs-source-dirs: src | 70 | hs-source-dirs: src |
70 | default-language: Haskell2010 | 71 | default-language: Haskell2010 |
71 | ghc-options: -Wall | 72 | ghc-options: -Wall |
diff --git a/server/thermoprint-server.nix b/server/thermoprint-server.nix index 6ff8b10..ff8ebd4 100644 --- a/server/thermoprint-server.nix +++ b/server/thermoprint-server.nix | |||
@@ -1,7 +1,7 @@ | |||
1 | { mkDerivation, async, base, binary, bytestring, conduit | 1 | { mkDerivation, async, base, binary, bytestring, conduit |
2 | , containers, data-default-class, deepseq, dyre, either, encoding | 2 | , constraints, containers, data-default-class, deepseq, dyre |
3 | , exceptions, extended-reals, filelock, hspec, mmorph | 3 | , either, encoding, exceptions, extended-reals, filelock, hspec |
4 | , monad-control, monad-logger, mtl, network-uri, persistent | 4 | , mmorph, monad-control, monad-logger, mtl, network-uri, persistent |
5 | , persistent-sqlite, persistent-template, QuickCheck | 5 | , persistent-sqlite, persistent-template, QuickCheck |
6 | , quickcheck-instances, resourcet, servant, servant-server, stdenv | 6 | , quickcheck-instances, resourcet, servant, servant-server, stdenv |
7 | , stm, temporary, text, thermoprint-client, thermoprint-spec, time | 7 | , stm, temporary, text, thermoprint-client, thermoprint-spec, time |
@@ -14,12 +14,13 @@ mkDerivation { | |||
14 | isLibrary = true; | 14 | isLibrary = true; |
15 | isExecutable = true; | 15 | isExecutable = true; |
16 | libraryHaskellDepends = [ | 16 | libraryHaskellDepends = [ |
17 | base binary bytestring conduit containers data-default-class | 17 | base binary bytestring conduit constraints containers |
18 | deepseq dyre either encoding exceptions extended-reals filelock | 18 | data-default-class deepseq dyre either encoding exceptions |
19 | mmorph monad-control monad-logger mtl network-uri persistent | 19 | extended-reals filelock mmorph monad-control monad-logger mtl |
20 | persistent-template QuickCheck quickcheck-instances resourcet | 20 | network-uri persistent persistent-template QuickCheck |
21 | servant servant-server stm text thermoprint-spec time transformers | 21 | quickcheck-instances resourcet servant servant-server stm text |
22 | wai wai-websockets warp websockets | 22 | thermoprint-spec time transformers wai wai-websockets warp |
23 | websockets | ||
23 | ]; | 24 | ]; |
24 | executableHaskellDepends = [ | 25 | executableHaskellDepends = [ |
25 | base monad-logger mtl persistent-sqlite resourcet | 26 | base monad-logger mtl persistent-sqlite resourcet |