Long polling in Yesod
Asked Answered
H

2

8

Can I do long polling in Yesod, or any other Haskell web framework with comparable database facilities?

To be precise, I want to delay a HTTP response until something interesting happens. There should also be a timeout after which the client will be served a response saying "nothing happened" and then the client will issue the same request.

To make life even more complicated, the app I have in mind is serving all its stuff over both HTTP/HTML5 and a really compact UDP protocol to MIDP clients. Events from either protocol can release responses in either protocol.

TIA, Adrian.

Hangbird answered 10/6, 2013 at 11:16 Comment(0)
D
7

I can't answer all the issues of the more complicated UDP stuff, but the short answer is that, yes, Yesod supports long polling. You can essentially do something like:

myHandler = do
    mres <- timeout timeoutInMicroseconds someAction
    case mres of
        Nothing -> return nothingHappenedResponse
        Just res -> doSomething res

You'll probably want to used System.Timeout.Lifted from the lifted-base package.

Decompound answered 10/6, 2013 at 14:37 Comment(2)
Would this procedure exhaust threads on the server if faced with lots of requests? I came here after following the discussion of #406450Anhwei
GHC's runtime supports a very large number of green threads. I highly doubt that the number of threads will end up being the limiting factor on resources.Decompound
S
4

Michael's answer hits the timeout requirement. For general clients you do not want to keep HTTP responses waiting for more than about 60 seconds as they may be connecting through a proxy or similar which tend to get impatient after about that long. If you're on a more tightly controlled network then you may be able to relax this timeout. One minor correction is that the parameter to timeout is in microseconds not nanoseconds.

For the 'wait for something interesting to happen' part, we use the check combinator from Control.Concurrent.STM (which wraps up retry) so our handler thread waits on a TVar:

someAction = do
    interestingStuff <- atomically $ do
        currentStuff <- readTVar theStuff
        check $ isInteresting currentStuff
        return currentStuff
    respondWith interestingStuff

Meanwhile, other threads (incl HTTP handlers) are updating theStuff :: TVar Stuff - each update triggers a new calculation of isInteresting and potentially a response if it returns True.

This is compatible with serving the same information over UDP: simply share theStuff between your UDP server threads and the Yesod threads.

Schoolmistress answered 15/12, 2014 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.