Problem with continuations/flow.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Problem with continuations/flow.

Tobias Pape
Hi.


Calling the following:

testCC

        self inform: 'A'.  
        self wait: [ :cc |
                self inform: 'B: ', ( self session actionUrlForContinuation: cc).
                self answer].
        self inform: 'C'.
        self answer.  
       

allways results in an error:

Error: This block accepts 1 argument, but was called with 0 arguments.

In WASession>>handleFiltered:

handleFiltered: aRequestContext
        | key continuation |
        key := aRequestContext request fields
                at: self actionField
                ifAbsent: [ ^ self start ].
               
        continuation := continuations
                at: key
                ifAbsent: [ ^ self unknownRequest ].
        continuation value

at the last line.
Continuation is
        outerContext: GRPharoPlatform>>seasideSuspendFlowDo: startpc: 54 numArgs: 1


So Long,
        -Tobias

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Problem with continuations/flow.

Tobias Pape

Am 2011-05-20 um 09:49 schrieb Tobias Pape:

> Hi.
>
>
> Calling the following:
>
> testCC
>
> self inform: 'A'.  
> self wait: [ :cc |
> self inform: 'B: ', ( self session actionUrlForContinuation: cc).
> self answer].
> self inform: 'C'.
> self answer.  
>
>
> allways results in an error:
>

Ok, this is incorret,
Calling the url generated by ( self session actionUrlForContinuation: cc)
results in the error.

> Error: This block accepts 1 argument, but was called with 0 arguments.
>
> In WASession>>handleFiltered:
>
> handleFiltered: aRequestContext
> | key continuation |
> key := aRequestContext request fields
> at: self actionField
> ifAbsent: [ ^ self start ].
>
> continuation := continuations
> at: key
> ifAbsent: [ ^ self unknownRequest ].
> continuation value
>
> at the last line.
> Continuation is
> outerContext: GRPharoPlatform>>seasideSuspendFlowDo: startpc: 54 numArgs: 1
>
>
> So Long,
> -Tobias
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Problem with continuations/flow.

Tobias Pape
*humble bump*

Am 2011-05-20 um 10:03 schrieb Tobias Pape:

>
> Am 2011-05-20 um 09:49 schrieb Tobias Pape:
>
>> Hi.
>>
>>
>> Calling the following:
>>
>> testCC
>>
>> self inform: 'A'.  
>> self wait: [ :cc |
>> self inform: 'B: ', ( self session actionUrlForContinuation: cc).
>> self answer].
>> self inform: 'C'.
>> self answer.  
>>
>>
>> allways results in an error:
>>
>
> Ok, this is incorret,
> Calling the url generated by ( self session actionUrlForContinuation: cc)
> results in the error.
>
>> Error: This block accepts 1 argument, but was called with 0 arguments.
>>
>> In WASession>>handleFiltered:
>>
>> handleFiltered: aRequestContext
>> | key continuation |
>> key := aRequestContext request fields
>> at: self actionField
>> ifAbsent: [ ^ self start ].
>>
>> continuation := continuations
>> at: key
>> ifAbsent: [ ^ self unknownRequest ].
>> continuation value
>>
>> at the last line.
>> Continuation is
>> outerContext: GRPharoPlatform>>seasideSuspendFlowDo: startpc: 54 numArgs: 1
>>
>>
>> So Long,
>> -Tobias
>>
>> _______________________________________________
>> seaside mailing list
>> [hidden email]
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Problem with continuations/flow.

Julian Fitzell-2
#actionUrlForContinuation: doesn't expect a first-class continuation
but rather a CPS continuation (a subclass of WASessionContinuation).
Actually, to be more accurate, WASession>>handleFiltered: expects that
to be so. Actually, to be more accurate, it expects something that
responds to successfully to #value.

Technically, I think you could avoid the error by doing:

testCC
     self inform: 'A'.
     self wait: [ :cc |
             self inform: 'B: ', ( self session
actionUrlForContinuation: [ cc value: nil ]) greaseString.
             self answer].
     self inform: 'C'.
     self answer.

However, I doubt you'll be happy with the results: part of the
implementation of WASessionContinuation>>value is to restore
backtracked state, and its subclasses do things like processing
callbacks and starting rendering. Without the handling that deals with
callbacks, for example, your call to #answer inside the block won't
work.

What are you trying to accomplish?

Julian

On Tue, May 24, 2011 at 6:50 AM, Tobias Pape <[hidden email]> wrote:

> *humble bump*
>
> Am 2011-05-20 um 10:03 schrieb Tobias Pape:
>
>>
>> Am 2011-05-20 um 09:49 schrieb Tobias Pape:
>>
>>> Hi.
>>>
>>>
>>> Calling the following:
>>>
>>> testCC
>>>
>>>      self inform: 'A'.
>>>      self wait: [ :cc |
>>>              self inform: 'B: ', ( self session actionUrlForContinuation: cc).
>>>              self answer].
>>>      self inform: 'C'.
>>>      self answer.
>>>
>>>
>>> allways results in an error:
>>>
>>
>> Ok, this is incorret,
>> Calling the url generated by ( self session actionUrlForContinuation: cc)
>> results in the error.
>>
>>> Error: This block accepts 1 argument, but was called with 0 arguments.
>>>
>>> In WASession>>handleFiltered:
>>>
>>> handleFiltered: aRequestContext
>>>      | key continuation |
>>>      key := aRequestContext request fields
>>>              at: self actionField
>>>              ifAbsent: [ ^ self start ].
>>>
>>>      continuation := continuations
>>>              at: key
>>>              ifAbsent: [ ^ self unknownRequest ].
>>>      continuation value
>>>
>>> at the last line.
>>> Continuation is
>>>      outerContext: GRPharoPlatform>>seasideSuspendFlowDo: startpc: 54 numArgs: 1
>>>
>>>
>>> So Long,
>>>      -Tobias
>>>
>>> _______________________________________________
>>> seaside mailing list
>>> [hidden email]
>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>
>> _______________________________________________
>> seaside mailing list
>> [hidden email]
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Problem with continuations/flow.

Tobias Pape

Am 2011-05-24 um 09:50 schrieb Julian Fitzell:

> #actionUrlForContinuation: doesn't expect a first-class continuation
> but rather a CPS continuation (a subclass of WASessionContinuation).
> Actually, to be more accurate, WASession>>handleFiltered: expects that
> to be so. Actually, to be more accurate, it expects something that
> responds to successfully to #value.
>
> Technically, I think you could avoid the error by doing:
>
> testCC
>     self inform: 'A'.
>     self wait: [ :cc |
>             self inform: 'B: ', ( self session
> actionUrlForContinuation: [ cc value: nil ]) greaseString.
>             self answer].
>     self inform: 'C'.
>     self answer.
>
> However, I doubt you'll be happy with the results: part of the
> implementation of WASessionContinuation>>value is to restore
> backtracked state, and its subclasses do things like processing
> callbacks and starting rendering. Without the handling that deals with
> callbacks, for example, your call to #answer inside the block won't
> work.


In the original Squeaksource Code, this facility was used to
generate Password-reset links like this (in seaside 2.7*):

  1 sendPasswordToUserWithLogin: login
  2 | member url |
  3 member := self model memberAt: login.
  4
  5 " validation here "
  6 Continuation currentDo: [ :cc |
  7 url := self session actionUrlForContinuation: cc.
  8 url := SSRepository rootUrl , url copyWithoutFirst.
  9 self sendMailWithUrl: url toMember: member. "exception handling here"
 10 self inform: 'An e-mail has been successfully sent to you.'.
 11 self answer ].
 12 self callEditMemberForm. "shortened for brevity"
 13 self answer.

with the effect, that on the website the ‘link to the continuation’ was
generated (7/8) and sent as email to se user (9). The user was informed
that the email had been sent (10) and was returned where he came from (11)
  Now when the user clicked on the link in the email, the continuation
continued from 12, effectively allowing the user to change her/his password.

I think this is one of the most elegant ways to implement a secure
password reset. Yet, this no longer works with Seaside 3.0,
Neither using
        WAComponent>>#wait: ,
        GRPlatform>>#seasideSuspendFlowDo: ,
        WAContinuation>>#currentDo: , nor
        WAPartialContinuation>>#currentDo:
(I tried the last with various marker setups)

I hope you can enlighten me there.

Best
        -Tobias



* for reference, the same from SqueakSource2 with Seaside 2.8, but
  the differences are minor.

sendPasswordToUserWithLogin: login
        | member url |
        member := self model memberAt: login.
        " " validation here "
        WAContinuation currentDo: [ :cc |
                url := self session actionUrlForContinuation: cc.
                url := self repository rootUrl , url copyWithoutFirst.
                self sendMailWithUrl: url toMember: member. "exception handling here"
                self inform: 'An e-mail has been successfully sent to you.'.
                self answer ].
        self editMember: 'Change your password'.
        self answer_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Problem with continuations/flow.

Julian Fitzell-2
I'm pretty sure that code would have suffered from the same bugs, i.e.
state would not be backtracked, so the user would be running in a
session assuming it was in the condition of a particular request but
actually in the state of whatever request happened to have been
processed by that session most recently. However, the move to partial
continuations means that it is now more overtly broken.

So... instead of using #inform: to tell the user an email has been
sent to them, you could #call: a component. Inside that component's
render method, you can use "url := html urlForAction [ self
verifyAccount. self answer ]" to get a URL and then send the email.
This isn't a *great* solution either, since we don't recommend
performing actions (like sending an email) during the render phase,
but currently you have no way of setting up callbacks in a task, so it
may be the best you can easily do.

The other option is to create your own subclass of
WASessionContinuation, which is a bit heavier-weight but probably a
better idea. I'm actually in the middle of working on some code in
Seaside that introduces a pluggable action continuation, which should
make this kind of thing easier since you wouldn't have to create your
own class. It should be possible to implement what you're trying to do
in a task by wrapping the first class continuation in a CPS
continuation, but I'll need to think a bit more about that - I'm
meeting Nick to work on related stuff this afternoon anyway so I'll
see what I can come up with.

Julian

On Tue, May 24, 2011 at 9:21 AM, Tobias Pape <[hidden email]> wrote:

>
> Am 2011-05-24 um 09:50 schrieb Julian Fitzell:
>
>> #actionUrlForContinuation: doesn't expect a first-class continuation
>> but rather a CPS continuation (a subclass of WASessionContinuation).
>> Actually, to be more accurate, WASession>>handleFiltered: expects that
>> to be so. Actually, to be more accurate, it expects something that
>> responds to successfully to #value.
>>
>> Technically, I think you could avoid the error by doing:
>>
>> testCC
>>     self inform: 'A'.
>>     self wait: [ :cc |
>>             self inform: 'B: ', ( self session
>> actionUrlForContinuation: [ cc value: nil ]) greaseString.
>>             self answer].
>>     self inform: 'C'.
>>     self answer.
>>
>> However, I doubt you'll be happy with the results: part of the
>> implementation of WASessionContinuation>>value is to restore
>> backtracked state, and its subclasses do things like processing
>> callbacks and starting rendering. Without the handling that deals with
>> callbacks, for example, your call to #answer inside the block won't
>> work.
>
>
> In the original Squeaksource Code, this facility was used to
> generate Password-reset links like this (in seaside 2.7*):
>
>  1 sendPasswordToUserWithLogin: login
>  2     | member url |
>  3     member := self model memberAt: login.
>  4
>  5     " validation here "
>  6     Continuation currentDo: [ :cc |
>  7             url := self session actionUrlForContinuation: cc.
>  8             url := SSRepository rootUrl , url copyWithoutFirst.
>  9             self sendMailWithUrl: url toMember: member. "exception handling here"
>  10             self inform: 'An e-mail has been successfully sent to you.'.
>  11             self answer ].
>  12     self callEditMemberForm. "shortened for brevity"
>  13     self answer.
>
> with the effect, that on the website the ‘link to the continuation’ was
> generated (7/8) and sent as email to se user (9). The user was informed
> that the email had been sent (10) and was returned where he came from (11)
>  Now when the user clicked on the link in the email, the continuation
> continued from 12, effectively allowing the user to change her/his password.
>
> I think this is one of the most elegant ways to implement a secure
> password reset. Yet, this no longer works with Seaside 3.0,
> Neither using
>        WAComponent>>#wait: ,
>        GRPlatform>>#seasideSuspendFlowDo: ,
>        WAContinuation>>#currentDo: , nor
>        WAPartialContinuation>>#currentDo:
> (I tried the last with various marker setups)
>
> I hope you can enlighten me there.
>
> Best
>        -Tobias
>
>
>
> * for reference, the same from SqueakSource2 with Seaside 2.8, but
>  the differences are minor.
>
> sendPasswordToUserWithLogin: login
>        | member url |
>        member := self model memberAt: login.
>        " " validation here "
>        WAContinuation currentDo: [ :cc |
>                url := self session actionUrlForContinuation: cc.
>                url := self repository rootUrl , url copyWithoutFirst.
>                self sendMailWithUrl: url toMember: member. "exception handling here"
>                self inform: 'An e-mail has been successfully sent to you.'.
>                self answer ].
>        self editMember: 'Change your password'.
>        self answer_______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Problem with continuations/flow.

Tobias Pape

Am 2011-05-24 um 12:02 schrieb Julian Fitzell:

> I'm pretty sure that code would have suffered from the same bugs, i.e.
> state would not be backtracked, so the user would be running in a
> session assuming it was in the condition of a particular request but
> actually in the state of whatever request happened to have been
> processed by that session most recently. However, the move to partial
> continuations means that it is now more overtly broken.
>
> So... instead of using #inform: to tell the user an email has been
> sent to them, you could #call: a component. Inside that component's
> render method, you can use "url := html urlForAction [ self
> verifyAccount. self answer ]" to get a URL and then send the email.
> This isn't a *great* solution either, since we don't recommend
> performing actions (like sending an email) during the render phase,
> but currently you have no way of setting up callbacks in a task, so it
> may be the best you can easily do.
>
> The other option is to create your own subclass of
> WASessionContinuation, which is a bit heavier-weight but probably a
> better idea. I'm actually in the middle of working on some code in
> Seaside that introduces a pluggable action continuation, which should
> make this kind of thing easier since you wouldn't have to create your
> own class. It should be possible to implement what you're trying to do
> in a task by wrapping the first class continuation in a CPS
> continuation, but I'll need to think a bit more about that - I'm
> meeting Nick to work on related stuff this afternoon anyway so I'll
> see what I can come up with.

Thanks Julian for the explanation.
Interestingly, it is working for the original
SqueakSource. However I'm not reluctant to change the code.
I think, for SqueakSource, Dale has a working solution similar
to the one you stated with #urlForAction.

I'm interested in the outcome of your ‘journey’ into the
Continuations :)

Best
        -Tobias_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside