packages feed

jsaddle-warp-0.9.9.7: src/Language/Javascript/JSaddle/WebSockets/BatchSender.hs

module Language.Javascript.JSaddle.WebSockets.BatchSender
    ( withBatchSender
    ) where

import Control.Concurrent.Async (link, withAsync)
import Control.Concurrent.STM
    ( atomically, newEmptyTMVarIO, putTMVar, takeTMVar, tryTakeTMVar )
import Control.Monad (forever, void)
import Language.Javascript.JSaddle.Types (Batch)

-- | Send batches without blocking the pump.
-- Keep at most one active batch and one pending batch.
-- Sender failure interrupts connection.
-- On exit, cancel the sender and wait for it to stop.
--
-- This should be called only from the serial JSaddle batch pump.
-- Publish the next batch only after acknowledgement of the previous batch.
-- Replace only WebSocket copies of batches already delivered through HTTP.
withBatchSender :: (Batch -> IO ()) -> ((Batch -> IO ()) -> IO a) -> IO a
withBatchSender send action = do
    pending <- newEmptyTMVarIO
    let publish batch = atomically $ do
            void $ tryTakeTMVar pending
            putTMVar pending batch
        sender = forever $ atomically (takeTMVar pending) >>= send
    withAsync sender $ \worker -> do
        link worker
        action publish