aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/default-conf/Main.hs2
-rw-r--r--server/src/Thermoprint/Server.hs8
-rw-r--r--server/src/Thermoprint/Server/API.hs34
-rw-r--r--server/src/Thermoprint/Server/Printer.hs6
-rw-r--r--server/src/Thermoprint/Server/Printer/Generic.hs4
-rw-r--r--server/src/Thermoprint/Server/Queue.hs2
-rw-r--r--server/src/Thermoprint/Server/Queue/Utils.hs2
-rw-r--r--server/test/Thermoprint/ServerSpec.hs6
-rw-r--r--server/thermoprint-server.cabal2
9 files changed, 35 insertions, 31 deletions
diff --git a/server/default-conf/Main.hs b/server/default-conf/Main.hs
index 35088e8..6ea0ef7 100644
--- a/server/default-conf/Main.hs
+++ b/server/default-conf/Main.hs
@@ -15,7 +15,7 @@ import Control.Monad.Reader
15import Database.Persist.Sqlite 15import Database.Persist.Sqlite
16 16
17main :: IO () 17main :: IO ()
18main = thermoprintServer True (Nat runSqlite) $ def `withPrinters` printers 18main = thermoprintServer True (NT runSqlite) $ def `withPrinters` printers
19 where 19 where
20 runSqlite :: ReaderT ConnectionPool (LoggingT IO) a -> IO a 20 runSqlite :: ReaderT ConnectionPool (LoggingT IO) a -> IO a
21 runSqlite = runStderrLoggingT . withSqlitePool "thermoprint.sqlite" 1 . runReaderT 21 runSqlite = runStderrLoggingT . withSqlitePool "thermoprint.sqlite" 1 . runReaderT
diff --git a/server/src/Thermoprint/Server.hs b/server/src/Thermoprint/Server.hs
index 15fb651..a33a613 100644
--- a/server/src/Thermoprint/Server.hs
+++ b/server/src/Thermoprint/Server.hs
@@ -111,7 +111,7 @@ instance MonadIO m => Default (Config m) where
111 } 111 }
112 112
113instance MonadIO m => Default (QMConfig m) where 113instance MonadIO m => Default (QMConfig m) where
114 def = QMConfig idQM $ Nat (liftIO . runIdentityT) 114 def = QMConfig idQM $ NT (liftIO . runIdentityT)
115 115
116withPrinters :: MonadResource m => Config m -> [(m PrinterMethod, QMConfig m)] -> m (Config m) 116withPrinters :: MonadResource m => Config m -> [(m PrinterMethod, QMConfig m)] -> m (Config m)
117-- ^ Add a list of printers to a 'Config' 117-- ^ Add a list of printers to a 'Config'
@@ -149,7 +149,7 @@ thermoprintServer dyre io cfg = do
149 , Dyre.cacheDir = return <$> cacheDir 149 , Dyre.cacheDir = return <$> cacheDir
150 } 150 }
151 where 151 where
152 realMain cfg = unNat (io . Nat runResourceT) $ do 152 realMain cfg = (io . NT runResourceT) $$ do
153 tMgr <- threadManager resourceForkIO 153 tMgr <- threadManager resourceForkIO
154 flip finally (cleanup tMgr) $ do 154 flip finally (cleanup tMgr) $ do
155 Config{..} <- cfg 155 Config{..} <- cfg
@@ -159,11 +159,11 @@ thermoprintServer dyre io cfg = do
159 gcChan <- liftIO newTChanIO 159 gcChan <- liftIO newTChanIO
160 fork tMgr $ jobGC gcChan 160 fork tMgr $ jobGC gcChan
161 let 161 let
162 runQM' (queueManagers -> QMConfig qm nat) printer = unNat nat $ runQM gcChan qm printer 162 runQM' (queueManagers -> QMConfig qm nat) printer = nat $$ runQM gcChan qm printer
163 mapM_ (fork tMgr . uncurry runQM') $ Map.toList printers 163 mapM_ (fork tMgr . uncurry runQM') $ Map.toList printers
164 nChan <- liftIO $ newBroadcastTChanIO 164 nChan <- liftIO $ newBroadcastTChanIO
165 let 165 let
166 printerUrl :: API.PrinterId -> URI 166 printerUrl :: API.PrinterId -> URI
167 printerUrl = safeLink thermoprintAPI (Proxy :: Proxy ("jobs" :> QueryParam "printer" API.PrinterId :> Get '[JSON] (Seq (API.JobId, UTCTime, JobStatus)))) . Just 167 printerUrl = linkURI . safeLink thermoprintAPI (Proxy :: Proxy ("jobs" :> QueryParam "printer" API.PrinterId :> Get '[JSON] (Seq (API.JobId, UTCTime, JobStatus)))) . Just
168 mapM_ (fork tMgr . uncurry (notifyOnChange nChan ((==) `on` fromZipper)) . bimap printerUrl queue) $ Map.toList printers 168 mapM_ (fork tMgr . uncurry (notifyOnChange nChan ((==) `on` fromZipper)) . bimap printerUrl queue) $ Map.toList printers
169 liftIO . Warp.runSettings warpSettings . withPush nChan . serve thermoprintAPI . flip enter API.thermoprintServer =<< handlerNat printers nChan 169 liftIO . Warp.runSettings warpSettings . withPush nChan . serve thermoprintAPI . flip enter API.thermoprintServer =<< handlerNat printers nChan
diff --git a/server/src/Thermoprint/Server/API.hs b/server/src/Thermoprint/Server/API.hs
index f7a8576..30ef290 100644
--- a/server/src/Thermoprint/Server/API.hs
+++ b/server/src/Thermoprint/Server/API.hs
@@ -29,6 +29,7 @@ import qualified Data.Text as T
29 29
30import Servant hiding (Handler) 30import Servant hiding (Handler)
31import Servant.Server hiding (Handler) 31import Servant.Server hiding (Handler)
32import qualified Servant.Server as Servant (Handler(..))
32import Servant.Utils.Enter 33import Servant.Utils.Enter
33import Servant.Utils.Links 34import Servant.Utils.Links
34 35
@@ -75,8 +76,8 @@ data HandlerInput = HandlerInput { sqlPool :: ConnectionPool -- ^ How to intera
75 76
76handlerNat :: ( MonadReader ConnectionPool m 77handlerNat :: ( MonadReader ConnectionPool m
77 , MonadLoggerIO m 78 , MonadLoggerIO m
78 ) => Map PrinterId Printer -> TChan Notification -> m (Handler :~> ExceptT ServantErr IO) 79 ) => Map PrinterId Printer -> TChan Notification -> m (Handler :~> Servant.Handler)
79-- ^ Servant requires its handlers to be 'ExceptT ServantErr IO' 80-- ^ Servant requires its handlers to be essentially 'ExceptT ServantErr IO'
80-- 81--
81-- This generates a 'Nat'ural transformation for squashing the monad-transformer-stack we use in our handlers to the monad 'servant-server' wants 82-- This generates a 'Nat'ural transformation for squashing the monad-transformer-stack we use in our handlers to the monad 'servant-server' wants
82handlerNat printerMap nChan = do 83handlerNat printerMap nChan = do
@@ -89,8 +90,11 @@ handlerNat printerMap nChan = do
89 , nChan = nChan 90 , nChan = nChan
90 } 91 }
91 protoNat :: ProtoHandler :~> IO 92 protoNat :: ProtoHandler :~> IO
92 protoNat = Nat runResourceT . Nat (($ logFunc) . runLoggingT) . runReaderTNat handlerInput 93 protoNat = NT runResourceT . NT (($ logFunc) . runLoggingT) . runReaderTNat handlerInput
93 return $ hoistNat protoNat 94 return $ NT Servant.Handler . hoistNat protoNat
95
96runSql :: ReaderT SqlBackend ProtoHandler a -> Handler a
97runSql act = lift $ runSqlPool act =<< asks sqlPool
94 98
95thermoprintServer :: ServerT ThermoprintAPI Handler 99thermoprintServer :: ServerT ThermoprintAPI Handler
96-- ^ A 'servant-server' for 'ThermoprintAPI' 100-- ^ A 'servant-server' for 'ThermoprintAPI'
@@ -157,7 +161,7 @@ listJobs pId idR timeR = fmap (filterJobs . extractJobs) . (\(a, b) -> (,) a
157 ) 161 )
158 162
159getJob :: API.JobId -> Handler Printout 163getJob :: API.JobId -> Handler Printout
160getJob jobId = fmap jobContent . maybe (throwError err404) return =<< runSqlPool (get $ castId jobId) =<< asks sqlPool 164getJob jobId = fmap jobContent . maybe (throwError err404) return =<< runSql (get $ castId jobId)
161 165
162jobStatus :: API.JobId -> Handler JobStatus 166jobStatus :: API.JobId -> Handler JobStatus
163jobStatus jobId = maybe (throwError err404) return . lookup jobId . map (\(id, _, st) -> (id, st)) . toList =<< listJobs Nothing Nothing Nothing 167jobStatus jobId = maybe (throwError err404) return . lookup jobId . map (\(id, _, st) -> (id, st)) . toList =<< listJobs Nothing Nothing Nothing
@@ -174,36 +178,36 @@ abortJob needle = do
174 return . not $ ((==) `on` length) pending filtered 178 return . not $ ((==) `on` length) pending filtered
175 when found $ do 179 when found $ do
176 $(logInfo) $ "Removed job #" <> (T.pack $ show (castId needle :: Integer)) <> " from " <> (T.pack . show $ pId') 180 $(logInfo) $ "Removed job #" <> (T.pack $ show (castId needle :: Integer)) <> " from " <> (T.pack . show $ pId')
177 notify $ safeLink thermoprintAPI (Proxy :: Proxy ("jobs" :> Get '[JSON] (Seq (API.JobId, UTCTime, JobStatus)))) 181 notify . linkURI $ safeLink thermoprintAPI (Proxy :: Proxy ("jobs" :> Get '[JSON] (Seq (API.JobId, UTCTime, JobStatus))))
178 return found 182 return found
179 when (not found) $ throwError err404 183 when (not found) $ throwError err404
180 184
181listDrafts :: Handler (Map API.DraftId (Maybe DraftTitle)) 185listDrafts :: Handler (Map API.DraftId (Maybe DraftTitle))
182listDrafts = asks sqlPool >>= runSqlPool (selectSourceRes [] []) >>= flip with toMap 186listDrafts = runSql (selectSourceRes [] []) >>= lift . flip with toMap
183 where 187 where
184 toMap source = fmap Map.fromList . sourceToList $ (\(Entity key (Draft title _)) -> (castId key, title)) `mapOutput` source 188 toMap source = fmap Map.fromList . sourceToList $ (\(Entity key (Draft title _)) -> (castId key, title)) `mapOutput` source
185 189
186addDraft :: Maybe DraftTitle -> Printout -> Handler API.DraftId 190addDraft :: Maybe DraftTitle -> Printout -> Handler API.DraftId
187addDraft title content = do 191addDraft title content = do
188 id <- fmap castId . runSqlPool (insert $ Draft title content) =<< asks sqlPool 192 id <- castId <$> runSql (insert $ Draft title content)
189 $(logInfo) $ "Added draft #" <> (T.pack $ show (castId id :: Integer)) <> " (" <> (T.pack $ show title) <> ")" 193 $(logInfo) $ "Added draft #" <> (T.pack $ show (castId id :: Integer)) <> " (" <> (T.pack $ show title) <> ")"
190 notify $ safeLink thermoprintAPI (Proxy :: Proxy ("drafts" :> Get '[JSON] (Map API.DraftId (Maybe DraftTitle)))) 194 notify . linkURI $ safeLink thermoprintAPI (Proxy :: Proxy ("drafts" :> Get '[JSON] (Map API.DraftId (Maybe DraftTitle))))
191 return id 195 return id
192 196
193updateDraft :: API.DraftId -> Maybe DraftTitle -> Printout -> Handler () 197updateDraft :: API.DraftId -> Maybe DraftTitle -> Printout -> Handler ()
194updateDraft draftId title content = handle (\(KeyNotFound _) -> throwError $ err404) $ do 198updateDraft draftId title content = handle (\(KeyNotFound _) -> throwError $ err404) $ do
195 void . runSqlPool (updateGet (castId draftId) [ DraftTitle =. title, DraftContent =. content ]) =<< asks sqlPool 199 void . runSql $ updateGet (castId draftId) [ DraftTitle =. title, DraftContent =. content ]
196 $(logInfo) $ "Updated draft #" <> (T.pack $ show (castId draftId :: Integer)) 200 $(logInfo) $ "Updated draft #" <> (T.pack $ show (castId draftId :: Integer))
197 notify $ safeLink thermoprintAPI (Proxy :: Proxy ("draft" :> Capture "draftId" API.DraftId :> Get '[JSON] (Maybe DraftTitle, Printout))) $ draftId 201 notify . linkURI $ safeLink thermoprintAPI (Proxy :: Proxy ("draft" :> Capture "draftId" API.DraftId :> Get '[JSON] (Maybe DraftTitle, Printout))) $ draftId
198 202
199getDraft :: API.DraftId -> Handler (Maybe DraftTitle, Printout) 203getDraft :: API.DraftId -> Handler (Maybe DraftTitle, Printout)
200getDraft draftId = fmap (\(Draft title content) -> (title, content)) . maybe (throwError err404) return =<< runSqlPool (get $ castId draftId) =<< asks sqlPool 204getDraft draftId = fmap (\(Draft title content) -> (title, content)) . maybe (throwError err404) return =<< runSql (get $ castId draftId)
201 205
202deleteDraft :: API.DraftId -> Handler () 206deleteDraft :: API.DraftId -> Handler ()
203deleteDraft draftId = do 207deleteDraft draftId = do
204 runSqlPool (delete $ (castId draftId :: Key Draft)) =<< asks sqlPool 208 runSql $ delete (castId draftId :: Key Draft)
205 $(logInfo) $ "Made sure draft #" <> (T.pack $ show (castId draftId :: Integer)) <> " is Deleted" 209 $(logInfo) $ "Made sure draft #" <> (T.pack $ show (castId draftId :: Integer)) <> " is Deleted"
206 notify $ safeLink thermoprintAPI (Proxy :: Proxy ("drafts" :> Get '[JSON] (Map API.DraftId (Maybe DraftTitle)))) 210 notify . linkURI $ safeLink thermoprintAPI (Proxy :: Proxy ("drafts" :> Get '[JSON] (Map API.DraftId (Maybe DraftTitle))))
207 211
208printDraft :: API.DraftId -> Maybe PrinterId -> Handler API.JobId 212printDraft :: API.DraftId -> Maybe PrinterId -> Handler API.JobId
209printDraft draftId printerId = (\(Draft _ content) -> queueJob printerId content) =<< maybe (throwError err404) return =<< runSqlPool (get $ castId draftId) =<< asks sqlPool 213printDraft draftId printerId = (\(Draft _ content) -> queueJob printerId content) =<< maybe (throwError err404) return =<< runSql (get $ castId draftId)
diff --git a/server/src/Thermoprint/Server/Printer.hs b/server/src/Thermoprint/Server/Printer.hs
index 722d4ed..ae0c6a0 100644
--- a/server/src/Thermoprint/Server/Printer.hs
+++ b/server/src/Thermoprint/Server/Printer.hs
@@ -50,7 +50,7 @@ import Data.Time.Clock
50 50
51import Thermoprint.Server.Queue 51import Thermoprint.Server.Queue
52 52
53newtype PrinterMethod = PM { unPM :: forall m. (MonadResource m, MonadLogger m, MonadMask m) => Printout -> m (Maybe PrintingError) } 53newtype PrinterMethod = PM { unPM :: forall m. (MonadResource m, MonadLogger m, MonadMask m, MonadUnliftIO m) => Printout -> m (Maybe PrintingError) }
54 54
55data Printer = Printer 55data Printer = Printer
56 { print :: PrinterMethod 56 { print :: PrinterMethod
@@ -68,7 +68,7 @@ atomically' = liftIO . atomically
68 68
69runPrinter :: ( MonadReader ConnectionPool m 69runPrinter :: ( MonadReader ConnectionPool m
70 , MonadLogger m 70 , MonadLogger m
71 , MonadBaseControl IO m 71 , MonadUnliftIO m
72 , MonadResource m 72 , MonadResource m
73 , MonadMask m 73 , MonadMask m
74 ) => Printer -> m () 74 ) => Printer -> m ()
@@ -95,7 +95,7 @@ runPrinter Printer{..} = forever $ do
95addToQueue :: ( MonadReader ConnectionPool m 95addToQueue :: ( MonadReader ConnectionPool m
96 , MonadLogger m 96 , MonadLogger m
97 , MonadResource m 97 , MonadResource m
98 , MonadBaseControl IO m 98 , MonadUnliftIO m
99 ) => Printout -> Printer -> m JobId 99 ) => Printout -> Printer -> m JobId
100addToQueue printout Printer{..} = do 100addToQueue printout Printer{..} = do
101 jobId <- runSqlPool (insert $ Job printout) =<< ask 101 jobId <- runSqlPool (insert $ Job printout) =<< ask
diff --git a/server/src/Thermoprint/Server/Printer/Generic.hs b/server/src/Thermoprint/Server/Printer/Generic.hs
index ce818ee..441c74d 100644
--- a/server/src/Thermoprint/Server/Printer/Generic.hs
+++ b/server/src/Thermoprint/Server/Printer/Generic.hs
@@ -63,10 +63,10 @@ import Prelude hiding (mapM_, sequence_, lines)
63genericPrint :: FilePath -> PrinterMethod 63genericPrint :: FilePath -> PrinterMethod
64genericPrint path = PM $ genericPrint' path 64genericPrint path = PM $ genericPrint' path
65 65
66genericPrint' :: (MonadIO m, MonadMask m, MonadLogger m) => FilePath -> Printout -> m (Maybe PrintingError) 66genericPrint' :: (MonadIO m, MonadMask m, MonadLogger m, MonadUnliftIO m) => FilePath -> Printout -> m (Maybe PrintingError)
67genericPrint' path = flip catches handlers . withFile path . print 67genericPrint' path = flip catches handlers . withFile path . print
68 where 68 where
69 withFile path f = flip withEx f $ mkAcquire (openFile path WriteMode >>= (\h -> h <$ hSetBuffering h NoBuffering)) hClose 69 withFile path f = flip with f $ mkAcquire (openFile path WriteMode >>= (\h -> h <$ hSetBuffering h NoBuffering)) hClose
70 handlers = [ Handler $ return . Just . IOError . (show :: IOException -> String) 70 handlers = [ Handler $ return . Just . IOError . (show :: IOException -> String)
71 , Handler $ return . Just . EncError 71 , Handler $ return . Just . EncError
72 , Handler $ return . Just 72 , Handler $ return . Just
diff --git a/server/src/Thermoprint/Server/Queue.hs b/server/src/Thermoprint/Server/Queue.hs
index aa26fe3..fb5deb9 100644
--- a/server/src/Thermoprint/Server/Queue.hs
+++ b/server/src/Thermoprint/Server/Queue.hs
@@ -180,7 +180,7 @@ runQM gcChan qm (extractQueue -> q) = sleep =<< qm'
180 | otherwise = return () 180 | otherwise = return ()
181 181
182jobGC :: ( MonadReader ConnectionPool m 182jobGC :: ( MonadReader ConnectionPool m
183 , MonadBaseControl IO m 183 , MonadUnliftIO m
184 , MonadIO m 184 , MonadIO m
185 ) => TChan JobId -> m () 185 ) => TChan JobId -> m ()
186-- ^ Listen for 'JobId's on a 'TChan' and delete them from the database 'forever' 186-- ^ Listen for 'JobId's on a 'TChan' and delete them from the database 'forever'
diff --git a/server/src/Thermoprint/Server/Queue/Utils.hs b/server/src/Thermoprint/Server/Queue/Utils.hs
index 745053e..0255250 100644
--- a/server/src/Thermoprint/Server/Queue/Utils.hs
+++ b/server/src/Thermoprint/Server/Queue/Utils.hs
@@ -22,7 +22,7 @@ import Servant.Utils.Enter
22import Thermoprint.Server.Queue 22import Thermoprint.Server.Queue
23 23
24standardCollapse :: MonadIO m => IdentityT IO :~> m 24standardCollapse :: MonadIO m => IdentityT IO :~> m
25standardCollapse = Nat $ liftIO . runIdentityT 25standardCollapse = NT $ liftIO . runIdentityT
26 26
27standardSleep :: Monad (QueueManagerM t) => QueueManager t 27standardSleep :: Monad (QueueManagerM t) => QueueManager t
28-- ^ Instruct 'runQM' to sleep some standard amount of time 28-- ^ Instruct 'runQM' to sleep some standard amount of time
diff --git a/server/test/Thermoprint/ServerSpec.hs b/server/test/Thermoprint/ServerSpec.hs
index 334f785..d1dadba 100644
--- a/server/test/Thermoprint/ServerSpec.hs
+++ b/server/test/Thermoprint/ServerSpec.hs
@@ -85,13 +85,13 @@ setup startup = withSystemTempFile "thermoprint.sqlite" $ \fp h -> hClose h >> d
85 runSqlite = runStderrLoggingT . filterLogger (const (> LevelDebug)) . withSqlitePool (T.pack fp) 1 . runReaderT 85 runSqlite = runStderrLoggingT . filterLogger (const (> LevelDebug)) . withSqlitePool (T.pack fp) 1 . runReaderT
86 86
87 printers = [ ( pure $ S.PM tPM 87 printers = [ ( pure $ S.PM tPM
88 , S.QMConfig ((join . lift $ takeTMVar (manage tManager) <* signalTSem (ran tManager)) >> return 0) (Nat $ liftIO . runIdentityT) 88 , S.QMConfig ((join . lift $ takeTMVar (manage tManager) <* signalTSem (ran tManager)) >> return 0) (NT $ liftIO . runIdentityT)
89 ) 89 )
90 ] 90 ]
91 91
92 tPM :: MonadIO m => Printout -> m (Maybe PrintingError) 92 tPM :: MonadIO m => Printout -> m (Maybe PrintingError)
93 tPM printout = liftIO . atomically $ putTMVar (outputChan tPrinter) printout >> tryTakeTMVar (failSwitch tPrinter) 93 tPM printout = liftIO . atomically $ putTMVar (outputChan tPrinter) printout >> tryTakeTMVar (failSwitch tPrinter)
94 RunningServer <$> forkFinally (S.thermoprintServer False (Nat runSqlite) $ def' `S.withPrinters` printers) (putMVar term) <*> pure term <*> pure startSem <*> pure tPrinter <*> pure tManager 94 RunningServer <$> forkFinally (S.thermoprintServer False (NT runSqlite) $ def' `S.withPrinters` printers) (putMVar term) <*> pure term <*> pure startSem <*> pure tPrinter <*> pure tManager
95 where 95 where
96 def' :: MonadIO m => S.Config m 96 def' :: MonadIO m => S.Config m
97 def' = S.def { S.warpSettings = setBeforeMainLoop (signalQSem startup) $ defaultSettings } 97 def' = S.def { S.warpSettings = setBeforeMainLoop (signalQSem startup) $ defaultSettings }
@@ -158,7 +158,7 @@ spec = withSetup $ do
158 where 158 where
159 Client{..} = mkClient' $ BaseUrl Http "localhost" 3000 "" 159 Client{..} = mkClient' $ BaseUrl Http "localhost" 3000 ""
160 is404 :: ServantError -> Bool 160 is404 :: ServantError -> Bool
161 is404 e@(FailureResponse {}) = statusCode (responseStatus e) == 404 161 is404 (FailureResponse e) = statusCode (responseStatusCode e) == 404
162 is404 _ = False 162 is404 _ = False
163 163
164 164
diff --git a/server/thermoprint-server.cabal b/server/thermoprint-server.cabal
index 1ed55a6..28c29d7 100644
--- a/server/thermoprint-server.cabal
+++ b/server/thermoprint-server.cabal
@@ -37,7 +37,7 @@ library
37 , data-default-class >=0.0.1 && <1 37 , data-default-class >=0.0.1 && <1
38 , deepseq >=1.4.1 && <2 38 , deepseq >=1.4.1 && <2
39 , dyre >=0.8.12 && <1 39 , dyre >=0.8.12 && <1
40 , either >=4.4.1 && <5 40 , either >=4.4.1 && <6
41 , exceptions >=0.8.0 && <1 41 , exceptions >=0.8.0 && <1
42 , monad-control >=1.0.0 && <2 42 , monad-control >=1.0.0 && <2
43 , monad-logger >=0.3.13 && <1 43 , monad-logger >=0.3.13 && <1