diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-01-23 13:58:16 +0000 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-01-23 13:58:16 +0000 |
| commit | 0a5b8082e5ddcd22b846cc7c145af2468c542fa4 (patch) | |
| tree | 6c451253a17569ed5f7d1c1942a150863083e2b3 /server | |
| parent | 19df7b59fef57b75d6dc6d23dc0cd0c79bc39028 (diff) | |
| download | thermoprint-0a5b8082e5ddcd22b846cc7c145af2468c542fa4.tar thermoprint-0a5b8082e5ddcd22b846cc7c145af2468c542fa4.tar.gz thermoprint-0a5b8082e5ddcd22b846cc7c145af2468c542fa4.tar.bz2 thermoprint-0a5b8082e5ddcd22b846cc7c145af2468c542fa4.tar.xz thermoprint-0a5b8082e5ddcd22b846cc7c145af2468c542fa4.zip | |
runPrinter
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/Thermoprint/Server/Printer.hs | 65 | ||||
| -rw-r--r-- | server/thermoprint-server.cabal | 1 | ||||
| -rw-r--r-- | server/thermoprint-server.nix | 10 |
3 files changed, 64 insertions, 12 deletions
diff --git a/server/src/Thermoprint/Server/Printer.hs b/server/src/Thermoprint/Server/Printer.hs index e66afff..0db98a0 100644 --- a/server/src/Thermoprint/Server/Printer.hs +++ b/server/src/Thermoprint/Server/Printer.hs | |||
| @@ -1,29 +1,80 @@ | |||
| 1 | {-# LANGUAGE RankNTypes #-} | 1 | {-# LANGUAGE RankNTypes #-} |
| 2 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
| 3 | {-# LANGUAGE FlexibleContexts #-} | ||
| 4 | {-# LANGUAGE RecordWildCards #-} | ||
| 5 | {-# LANGUAGE OverloadedStrings #-} | ||
| 6 | {-# LANGUAGE TemplateHaskell #-} | ||
| 7 | {-# LANGUAGE StandaloneDeriving #-} | ||
| 8 | {-# LANGUAGE DeriveGeneric, DeriveAnyClass #-} | ||
| 2 | 9 | ||
| 3 | module Thermoprint.Server.Printer | 10 | module Thermoprint.Server.Printer |
| 4 | ( Printer | 11 | ( Printer(..) |
| 12 | , Queue(..) | ||
| 13 | , runPrinter | ||
| 5 | ) where | 14 | ) where |
| 6 | 15 | ||
| 7 | import Thermoprint.API (PrintingError(..), Printout) | 16 | import Thermoprint.API (PrintingError(..), Printout) |
| 17 | import qualified Thermoprint.API as API (JobStatus(..)) | ||
| 8 | 18 | ||
| 9 | import Thermoprint.Server.Database | 19 | import Thermoprint.Server.Database |
| 10 | 20 | ||
| 11 | import Database.Persist | 21 | import Database.Persist |
| 12 | import Database.Persist.Sql | 22 | import Database.Persist.Sql |
| 13 | 23 | ||
| 14 | import Data.Sequence (Seq, ViewL(..)) | 24 | import Data.Sequence (Seq, ViewL(..), viewl, (<|)) |
| 15 | import qualified Data.Sequence as Seq | 25 | import qualified Data.Sequence as Seq |
| 16 | import Data.Map (Map) | 26 | import Data.Map (Map) |
| 17 | import qualified Data.Map as Map | 27 | import qualified Data.Map as Map |
| 18 | 28 | ||
| 19 | import Control.Monad.IO.Class (MonadIO) | 29 | import qualified Data.Text as T (pack) |
| 30 | |||
| 31 | import Data.Typeable (Typeable) | ||
| 32 | import GHC.Generics (Generic) | ||
| 33 | import Control.DeepSeq | ||
| 34 | |||
| 35 | import Control.Monad.Trans.Resource | ||
| 36 | import Control.Monad.IO.Class | ||
| 37 | import Control.Monad.Logger | ||
| 38 | import Control.Monad.Reader | ||
| 39 | |||
| 40 | import Control.Monad (forever) | ||
| 20 | 41 | ||
| 21 | import Control.Concurrent.STM | 42 | import Control.Concurrent.STM |
| 22 | 43 | ||
| 23 | data Printer = Printer | 44 | data Printer = Printer |
| 24 | { print :: forall m. (MonadIO m) => Printout -> m (Maybe PrintingError) | 45 | { print :: forall m. (MonadIO m) => Printout -> m (Maybe PrintingError) |
| 25 | , queue :: TVar (Seq JobId) | 46 | , queue :: TVar Queue |
| 26 | } | 47 | } |
| 27 | 48 | ||
| 28 | runPrinter :: Printer -> IO () | 49 | -- | Zipper for 'Seq JobId' |
| 29 | runPrinter = undefined | 50 | data Queue = Queue |
| 51 | { pending :: Seq JobId -- ^ Pending jobs, closest first | ||
| 52 | , current :: Maybe JobId | ||
| 53 | , history :: Seq (JobId, Maybe PrintingError) -- ^ Completed jobs, closest first | ||
| 54 | } | ||
| 55 | deriving (Typeable, Generic, NFData) | ||
| 56 | |||
| 57 | atomically' :: MonadIO m => STM a -> m a | ||
| 58 | atomically' = liftIO . atomically | ||
| 59 | |||
| 60 | runPrinter :: ( MonadReader ConnectionPool m | ||
| 61 | , MonadIO m | ||
| 62 | , MonadLogger m | ||
| 63 | , MonadBaseControl IO m | ||
| 64 | ) => Printer -> m () | ||
| 65 | -- ^ Loop 'forever' pushing entries from the 'Queue' associated to a 'Printer' into its 'print'-method | ||
| 66 | runPrinter Printer{..} = forever $ do | ||
| 67 | jobId <- atomically' $ do | ||
| 68 | (Queue queuePending Nothing history) <- readTVar queue | ||
| 69 | case viewl queuePending of | ||
| 70 | EmptyL -> retry | ||
| 71 | (jobId :< remaining) -> do | ||
| 72 | writeTVar queue $!! Queue remaining (Just jobId) history | ||
| 73 | return jobId | ||
| 74 | job <- runSqlPool (get jobId) =<< ask | ||
| 75 | case job of | ||
| 76 | Nothing -> $(logWarn) "Nonexistent job id in printer queue" | ||
| 77 | Just job -> do | ||
| 78 | printReturn <- print (jobContent job) | ||
| 79 | maybe (return ()) ($(logWarn) . T.pack . (("Error while printing " ++ show jobId ++ ": ") ++) . show) $ printReturn | ||
| 80 | atomically' $ modifyTVar' queue (\Queue{..} -> force . Queue pending Nothing $ (jobId, printReturn) <| history) | ||
diff --git a/server/thermoprint-server.cabal b/server/thermoprint-server.cabal index 8862255..926118d 100644 --- a/server/thermoprint-server.cabal +++ b/server/thermoprint-server.cabal | |||
| @@ -40,6 +40,7 @@ library | |||
| 40 | , either >=4.4.1 && <5 | 40 | , either >=4.4.1 && <5 |
| 41 | , text >=1.2.1 && <2 | 41 | , text >=1.2.1 && <2 |
| 42 | , stm >=2.4.4 && <3 | 42 | , stm >=2.4.4 && <3 |
| 43 | , deepseq >=1.4.1 && <2 | ||
| 43 | hs-source-dirs: src | 44 | hs-source-dirs: src |
| 44 | default-language: Haskell2010 | 45 | default-language: Haskell2010 |
| 45 | 46 | ||
diff --git a/server/thermoprint-server.nix b/server/thermoprint-server.nix index 57e94a3..69bff1d 100644 --- a/server/thermoprint-server.nix +++ b/server/thermoprint-server.nix | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | { mkDerivation, base, containers, data-default-class, dyre, either | 1 | { mkDerivation, base, containers, data-default-class, deepseq, dyre |
| 2 | , monad-logger, mtl, persistent, persistent-sqlite | 2 | , either, monad-logger, mtl, persistent, persistent-sqlite |
| 3 | , persistent-template, resourcet, servant-server, stdenv, stm, text | 3 | , persistent-template, resourcet, servant-server, stdenv, stm, text |
| 4 | , thermoprint-spec, transformers, wai, warp | 4 | , thermoprint-spec, transformers, wai, warp |
| 5 | }: | 5 | }: |
| @@ -10,9 +10,9 @@ mkDerivation { | |||
| 10 | isLibrary = true; | 10 | isLibrary = true; |
| 11 | isExecutable = true; | 11 | isExecutable = true; |
| 12 | libraryHaskellDepends = [ | 12 | libraryHaskellDepends = [ |
| 13 | base containers data-default-class dyre either monad-logger mtl | 13 | base containers data-default-class deepseq dyre either monad-logger |
| 14 | persistent persistent-template resourcet servant-server stm text | 14 | mtl persistent persistent-template resourcet servant-server stm |
| 15 | thermoprint-spec transformers wai warp | 15 | text thermoprint-spec transformers wai warp |
| 16 | ]; | 16 | ]; |
| 17 | executableHaskellDepends = [ | 17 | executableHaskellDepends = [ |
| 18 | base monad-logger mtl persistent-sqlite resourcet | 18 | base monad-logger mtl persistent-sqlite resourcet |
