On Fri, Jan 28, 2011 at 6:22 PM, tsuraan <[email protected]> wrote:
> I don't think I understand Haskell well enough to make sense of what's
> going on here. catchError takes an Iteratee and a function that
> transforms an exception into an Iteratee, and returns a third
> Iteratee. The typical Snap handler function is of type Snap (), and
> the functions I've been using (writeBS, modifyResponse) also return "m
> ()", where m is a Snap. I don't see what I need to do to lift my Snap
> () functions into Iteratee functions so that I can use catchError on
> them. Am I missing something obvious? I'm still pretty shaky on
> Haskell's types, so I'm guessing there's something that I just don't
> understand about how Iteratees and Snap () types work together.
I'll try to explain. Snap () handlers actually don't write any output;
instead they modify a per-thread "Response" object kept in state. The
actual bytes are sent by the output enumerator, which is a field of
the Response object.
Enumerators are basically functions which spool output to iteratees,
and iteratees are little state machines which receive input and
produce values as output, potentially doing IO as a side-effect. In
our case the output iteratee is a function which takes input chunks
and sends them out the HTTP socket, potentially with some encoding
applied.
Since no output is actually sent until the Snap () handler finishes
running, if you want to do long polling it would need to happen within
your output enumerator. This enumerator has type:
Enumerator ByteString IO a
which is
Step ByteString IO a -> Iteratee ByteString IO a
In other words, you get handed a write end, and you send chunks of
bytes to it. You can also do IO through the "MonadIO" instance for
Iteratee.
The socket end (an iteratee) can produce two kinds of errors: iteratee
errors (which you catch using "catchError") and asynchronous
exceptions (like "thread killed"), which you can catch using "catch"
or "finally" from Control.Monad.CatchIO. You would need to handle them
both in order to be sure your cleanup actions are run.
Alternatively, you can try to let the garbage collector handle this
for you by using Control.Concurrent.MVar.addMVarFinalizer, but that's
not a great solution since there are no guarantees about when your
resources will actually be freed.
Hope this helps.
G
--
Gregory Collins <[email protected]>
_______________________________________________
Snap mailing list
[email protected]
http://mailman-mail5.webfaction.com/listinfo/snap