Limiting the blocking time from reading a Chan (SSE in Servant)

I’m trying to implement a SSE (server sent event) endpoint for my app. Since I have to regularly send messages to keep the connection alive, I need to limit the blocking time that a call to readChan creates when the contents of the channel is empty (Control.Concurrent.Chan#readChan).

Does any function come to mind? Or, should I build this Handler differently?

sseH :: Env -> Handler EventSource
sseH env = liftIO $ do
  chan <- dupChan env.broadcastChan
  return (S.fromStepT (S.Yield keepAlive rest))
  where
    -- read from the channel, but for max 15 seconds
    -- if no message is received, send a keep-alive message
    rest = S.Effect $ do
      msg :: Maybe ServerEvent <- **undefined**
      return $ case msg of
        Just m -> S.Yield m rest
        Nothing -> S.Yield keepAlive rest

    keepAlive :: ServerEvent
    keepAlive = CommentEvent (fromByteString "keep-alive")

I just found timeout :: Int -> IO a -> IO (Maybe a) . It might just be exactly what I’m looking for.

1 Like

Alternatively, you could have a background thread that just sends keep alive messages. This way you no longer have to care how long the other thread blocks.

1 Like

Thought about that too, and I was split between the two ideas. I’ll try the other now that my first solution works!