cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ovidiu Predescu <ovi...@cup.hp.com>
Subject Re: first impressions on continuations idea
Date Tue, 05 Feb 2002 01:37:05 GMT
On Sat, 2 Feb 2002 02:05:36 -0000, Allan Erskine <a.erskine@cs.ucl.ac.uk> wrote:

> > Ah, I see your point. Allan and you propose a two level indirection
> > scheme to obtain the continuation. The first level is keyed by the
> > cookie, and points to the session object. The second level is keyed by
> > the URL and points to the continuation.
> 
> Gahh - this is getting complicated!  I didn't say that!  I think we're
> all coming from the same/different direction.

All right ;-), I'll tune in to your ideas.

> This is what I understand.  An executing program looks like this:
> 
> ---what happened then----->	!n!	>-----what will happen next (cc)
> -----
> 					-^-
> 					-^-
> 					what's happening now
> 
> where "what will happen next" is labelled cc to stand for the "current
> continuation" of that program.
> 
> Scheme is about the only language around that can obtain these cc's
> and manipulate them as first class values, and Ovidiu's created the
> amazing new schecoon project; hopefully easy manipulation of program
> continuations can go a long way towards solving everyone's
> web-app/flow-management woes.

Thanks, I hope that too.

> So a web-app that involves a computation over many pages can be written
> in the form of a normal program (in some familiar Java like syntax that
> gets interpreted to Scheme in the background):
> 
> Page start_page = new Page("start.xml");	//note, could also
> construct
> 	
> //programmatically
> Operation next_op = start_page.show().get_user_action();
> next_op.apply();
> 
> ...
> 
> class buy : Operation {
> 	apply() { remove cart contents from database; fleece customer }
> }
> 
> ...
> 
> In the above example, you'd expect to wait between showing the start
> page, and capturing the user's next action.  
> 
> ---blah Operation------>	!show()!	>-----get_user_action()
> (cc) -----
> 					-^-
> 					-^-
> 					what's happening now
> 
> 
> In the background, this would be achieved by capturing the current
> continuation (ie .get_user_action(); ...).  This would be stored on the
> server, and a continuation-ID representing it would be stored with the
> client (in the URL, or encoded on the page in a hidden field).  When the
> client posts their request, the cont-ID is used to fish the continuation
> out, and it continues to run on the server.  This is MAGIC;  we hardly
> even have to _think_ about our application flow.

That's exactly right, although I'm not sure we need OOP for the flow
language.

> Now what is even better, and where I think we were getting confused is
> that continuations can be used as a way to control what happens if a
> user decides to spawn multiple browsers, and use their back button
> willy-nilly.

Oh, I thought we were debating over how to encode the continuation id
in the request. Nevertheless the point you're raising about
controlling the continuation objects is a very valid one.

> Continuations can be used to respond to this situation in _whatever_ way
> we'd like.  All with minimal logic overhead.
> 
> Situation 1 - you want the user to be able to follow a single path
> through your app
> 
> Just use plain continuations as described above.  After running the
> continuation, you could replace it with a different one under the same
> ID, redirecting the user to a not-there-anymore page, should they have
> used back or the likes.

I like this approach, no extra logic to handle expired
continuations. Perhaps a URL from which the user can continue browsing
can also be passed to the continuation, so the user is not left out in
the air not knowing where to next.

> Situation 2 - you really want the user to be navigating two ways through
> your app in parallel (madness!)
> 
> Fish the continuation out, according to its ID.  Clone it, and run the
> clone.  Place the original back under the same ID, in case the mad user
> wants to run it under a different context (e.g. with different request
> parameters)

Unfortunately you cannot clone a continuation :-(

But that's OK, I don't think we need it anyway. When you clone the
browser window, the request on the server will wake up the same
continuation. What is important though is the path taken through the
application until the next continuation is stored. It is the next
continuation which really embeds the path followed by the application
from the previous point of interruption up until the current point.

This means that on the server side, we can have potentially a tree of
continuations corresponding to each individual user. A fork in the
tree would correspond to a point where the user cloned the browser
window.

> Situtation 3 - you want to allow the user to navigate many ways through
> the program, and you want to know what the *£@# is going on
> 
> Fish the continuation out, clone it, and run the clone with some
> side-data (e.g. something resembling a mutex as in threaded
> programming).  Create a new continuation from the first one by adding
> some corresponding side-data (another mutex say), and store this again
> under the original ID.
> 
> Now two parallel threads can run through your web-app, but still be
> under your _strict_ control!  You can know exactly what's going on, if
> you want to(!).

I'm afraid I don't understand this last point. How is it different
from 2) above? The continuations are accessible to you as an
application developer, although there isn't much to do with them,
other than invoking them.

> That really covers most cases, AFAIK.
> 
> All that needs settled is the following:
> 
> 1) Where to store the continuation ID client-side.  I think the only
> logical choice is as a request-param, either in a hidden field, or in
> the URL as a param (ie foo.com/buy?cont_id=4gf...).  I take back what I
> said about sessions.  Continuations will be used in a slightly different
> way, as we expect to be able to manage more with our continutations as
> envisaged with sessions/cookies.

Right. As I said in an earlier reply to Judson, I believe we should
leave options to the developer on where continuation ids should be
encoded in the URL. This cannot hurt anyway.

> 2) What language features to provide developers to express their
> application flow.  Ovidiu recommends a Java-like syntax, and I'd go with
> this.  I agree it would be good to provide them with a good abstraction
> for the continuations, should they want to get their hands dirty.  But
> it would also be very nice to provide and encourage a way of describing
> flow with anyone having to think about the continuations being used in
       ^^^^
       without?

> the background.

I agree, although we definitely need to explain the concepts to the
users of the system, and how this is different from anything they've
used.

> 3) How the new schecoon features are to interact with the current
> sitemap.  I'd suggest letting the sitemap do what it's good at.  I'd
> suggest only ONE point of reference in the sitemap to a part of
> application-flow that is to be managed by schecoon.  And for schecoon to
> manage all the URI's and parameters corresponding to actions.  Otherwise
> you end up duplicating concerns across both application flow, and the
> sitemap.
> 
> So definitely no sitemap entries corresponding to actions that are
> already dealt with by functions in the schecoon setup.  These should be
> automatically mapped onto URI's by name.  The sitemap should really just
> point to an application in a pipeline, and run all the corresponding
> transformations/aggregations on the resulting data.

Have you looked at the current sitemap in the Schecoon CVS repository?
It defines a way to invoke flow functions when a particular URL
matches. Things are a bit different thought than what you described
above, as from the sitemap you can invoke flow functions, just as
you'd call any other resource:

      <map:match pattern="function/(.*)">
        <map:call function="{1}">
          <map:param name="a" value="1"/>
          <map:param name="b" value="2"/>
          <map:param name="c" value="3"/>
        </map:call>
      </map:match>

What is missing right now, but will come soon, is the ability to
describe the flow scripts. When it's available, it'll look something
like this, as part of the <map:resources> section:

  <map:resource type="flow">
    <map:script src="pet-store.scm" language="scheme"/>
    <map:script src="shopping-cart.flow" language="jWebFlow"/>
  </map:resource>

This will make available to the sitemap the flow scripts, which could
be written either directly in Scheme or in the flow language, whose
syntax is yet to be defined. The Schecoon engine will parse the flow
scripts, and record the entry functions, for later access from the
sitemap.

To handle continuations, the sitemap will also need an entry that
handles them. Here's a way to encode the continuation id as an
argument in the GET request:

  <map:match pattern="/buy/(.*)">
    <map:call function="handle-continuation">
      <map:param name="kont-id" value="{kont}"/>
    </map:call>
  </map:match>

"handle-continuation" is the Schecoon function that deals with the
continuations. It takes as argument the continuation id, it identifies
the continuation object, and executes it. If a developer needs a more
complex scheme for validating the continuation, he/she can invoke a
function of his/her own that does the needed validation, and in the
end either invokes handle-continuation, or handles it on its own.

Does this makes sense? I'll try to implement these this week, and see
how it works.

Regards,
-- 
Ovidiu Predescu <ovidiu@cup.hp.com>
http://www.geocities.com/SiliconValley/Monitor/7464/ (GNU, Emacs, other stuff)

---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Mime
View raw message