[Seaside] How to [ ] ensure: [ ] and call:

Avi Bryant avi.bryant at gmail.com
Sun Jun 19 16:04:33 CEST 2005


On 6/17/05, Michel Bany <m.bany at wanadoo.fr> wrote:

> In VW, for some reason, the #call: triggers the execution of the
> #ensure: block which is
> not our intention. To make it work we had to rewrite the code to use a
> lower level api
> in a very circumvoluted "write-only" way.
> 
> Would the same happen in Squeak ?
> Is there any trick for avoiding this ?

Yes, I believe the same thing would happen in Squeak.  The problem is
that interactions between continuations and #ensure: are essentially
(and, I'd say, necessarily) undefined.

Consider this: the cleanup block passed to #ensure: is supposed to
execute as soon as the receiver block has "finished" executing.  This
might mean a normal completion of the block, or an abnormal
termination like an early return or an exception.  But eventually, one
or the other of these things is bound to happen, and the cleanup block
will run.

However, once you capture a continuation inside the receiver block,
you are preventing that block from ever really being considered
finished.  The continuation could always be invoked another time.  In
Seaside terms, if you #call: inside that block, someone could always
use the back button to make that call #answer again.  So when do you
run the cleanup block?  If you wait until the receiver block is
"finished", it'll never happen - or at least not until the
continuation is garbage collected, which is both unpredictable and
hard to catch.  The other option is to run the cleanup block every
time the receiver block is terminated, ie, on every instance of
invoking the continuation and then returning out of the block
(somehow; perhaps by sending an HTML response back to the user).  This
is the behavior you're seeing, and I admit that it's rarely what's
wanted, but it's marginally more useful than a cleanup block that
never ran at all.

So, I don't recommend mixing #call: and #ensure:.  If possible, I'd
suggest doing this kind of thing at the session level instead.  The
easiest is to either keep one connection open for the duration of the
session (connecting at #initialize and disconnecting at
#unregistered), or the duration of a single request (by wrapping
something like #withEscapeContinuationDo: with a connect/disconnect
pair).  Would either of those strategies work for you?

Avi


More information about the Seaside mailing list