aboutsummaryrefslogtreecommitdiff
path: root/server/src/Thermoprint/Server/Push.hs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/Thermoprint/Server/Push.hs')
-rw-r--r--server/src/Thermoprint/Server/Push.hs59
1 files changed, 59 insertions, 0 deletions
diff --git a/server/src/Thermoprint/Server/Push.hs b/server/src/Thermoprint/Server/Push.hs
new file mode 100644
index 0000000..b2eca6b
--- /dev/null
+++ b/server/src/Thermoprint/Server/Push.hs
@@ -0,0 +1,59 @@
1{-# LANGUAGE ViewPatterns #-}
2
3module Thermoprint.Server.Push
4 ( Notification
5 , withPush
6 , protocolSpec
7 , notifyOnChange
8 ) where
9
10import Network.WebSockets
11import Network.Wai.Handler.WebSockets
12import Network.Wai (Application)
13
14import Network.URI
15
16import Control.Concurrent.STM
17
18import Thermoprint.Server.Queue
19
20import Control.Monad.IO.Class
21import Control.Monad
22
23import Paths_thermoprint_server (version)
24import Data.Version (showVersion)
25
26import Data.ByteString.Char8 (ByteString)
27import qualified Data.ByteString.Char8 as CBS
28
29import Data.Text (Text)
30import qualified Data.Text as Text
31
32type Notification = URI
33
34withPush :: TChan Notification -> Application -> Application
35withPush chan = websocketsOr defaultConnectionOptions $ flip acceptRequestWith (AcceptRequest $ Just protocolSpec) >=> handleClient chan
36
37protocolSpec :: ByteString
38protocolSpec = CBS.pack $ "thermoprint-server.notification." ++ showVersion version
39
40handleClient :: TChan Notification -> Connection -> IO ()
41handleClient chan conn = do
42 cChan <- atomically $ dupTChan chan
43 forever . void $ atomically (readTChan cChan) >>= sendTextData conn . packNotification
44
45packNotification :: Notification -> Text
46packNotification = Text.pack . show
47
48notifyOnChange :: MonadIO m => TChan Notification -> (a -> a -> Bool) -> Notification -> TVar a -> m ()
49notifyOnChange chan cmp n q = void . liftIO $ readTVarIO q >>= notifyOnChange'
50 where
51 notifyOnChange' last = do
52 current <- atomically $ (\current -> current <$ check (not $ cmp last current)) =<< readTVar q
53 atomically $ writeTChan chan n
54 notifyOnChange' current
55
56
57
58
59