Asynchronous Participant

4 views
Skip to first unread message

Axyd

unread,
Mar 27, 2009, 10:25:28 PM3/27/09
to Ruote (OpenWFEru) users
Hello!

I read documentation available on the site but still haven't got an
idea how to create Asynchronous Participant.
It seems that JabberParticipant works this way, but I'm not sure.
Can you please suggest some ideas how to implement it?

Below there are 2 code samples, one - Synchronous, second Asynchronous
(pseudo code).

=================== Synchronous ===================
require 'openwfe/engine'

engine = OpenWFE::Engine.new(:definition_in_launchitem_allowed =>
true)

class AsynchronousProcess < OpenWFE::ProcessDefinition
sequence do
participant "Collect User Input"
participant "Display User Input"
end
end

engine.register_participant "Collect User Input" do |workitem|
workitem.user_input = "yes"
end

engine.register_participant "Display User Input" do |workitem|
p workitem.user_input
end

li = OpenWFE::LaunchItem.new(AsynchronousProcess)
fei = engine.launch(li)
engine.wait_for(fei)

=================== Asynchronous ===================
...
engine.register_participant "Collect User Input" do |workitem|
# Asynchronous call
UIService.send_mail_with_question_to_user(user, workitem.question)

# Asynchronous response
UIService.receive_mail_with_answer_from_user do |user, answer|
workitem.user_input = answer
end
end
...

Thanks :)

Axyd

unread,
Mar 27, 2009, 10:30:02 PM3/27/09
to Ruote (OpenWFEru) users
Or something like that maybe?
engine.register_participant "Collect User Input" do |workitem|
UIService.send_mail_with_question_to_user(user, workitem.question)
workitem.engine_wait_for_signal
end

UIService.receive_mail_with_answer_from_user do |user, answer|
engine.singnal{|workitem| workitem.user_input = answer}
end

John Mettraux

unread,
Mar 27, 2009, 10:49:40 PM3/27/09
to openwfe...@googlegroups.com

Hi Axyd,

I wrote a variation on your idea :

http://gist.github.com/87005

This variation uses a map user -> workitem, of course this is flawed,
since there could be multiple instances of this process each sending
an email to the same user...

The next variation assumes your mail service tracks a string
containing the identifier of the workitem/expression and it uses that
info when the answer comes back to retrieve the workitem and let the
engine resume :

http://gist.github.com/87010


Best regards,

--
John Mettraux - http://jmettraux.wordpress.com

Axyd

unread,
Mar 28, 2009, 9:37:15 AM3/28/09
to Ruote (OpenWFEru) users
Thanks for Samples and very fast Reply! :)

I did as you suggested and it works (remote service stores fei and
then returns it back with result)! Even if i persist process to disk
and then reload it. But i changed your sample a little and not sure i
did it right.

In you sample you used BlockParticipant, that calls 'reply' before the
result will be returned from the RemoteService. I implemented
AsyncParticipant, that doesn't call 'reply' on sending message, but
calls it when RemoteService returns it's answer.
Generally it works, but it seems that something strange goes with
Threads, it seems that AsyncParticipant.consume doesn't release it's
Thread until it calls 'reply'. I depicted it on Sequence Diagram here
http://docs.google.com/Doc?docid=dgpvsb45_13fsmp45gc&hl=en.
Problem highlighted with red.

The code for Sample (if you will be interested) is here:
async_participant.rb http://docs.google.com/Doc?docid=dgpvsb45_10fm69kxhg&hl=en
definitions.rb http://docs.google.com/Doc?docid=dgpvsb45_9ct4sdjgx&hl=en
question.rb http://docs.google.com/Doc?docid=dgpvsb45_11dpxg5vd4&hl=en
answer.rb http://docs.google.com/Doc?docid=dgpvsb45_12g7b2cvcj&hl=en

First runs 'question.rb', prints the question on console and then
exits.
Then runs 'answer.rb', restores Enine from disk, and waits for user
input on the console, then passes it to Engine.

Should i call 'reply' twice (on send and on receive)? Or there is
another way to release Thread? Or it's ok with it?

John Mettraux

unread,
Mar 28, 2009, 9:57:48 AM3/28/09
to openwfe...@googlegroups.com
On Sat, Mar 28, 2009 at 10:37 PM, Axyd <axy...@gmail.com> wrote:
>
> I did as you suggested and it works (remote service stores fei and
> then returns it back with result)! Even if i persist process to disk
> and then reload it. But i changed your sample a little and not sure i
> did it right.
>
> In you sample you used BlockParticipant, that calls 'reply' before the
> result will be returned from the RemoteService. I implemented
> AsyncParticipant, that doesn't call 'reply' on sending message, but
> calls it when RemoteService returns it's answer.
> Generally it works, but it seems that something strange goes with
> Threads, it seems that AsyncParticipant.consume doesn't release it's
> Thread until it calls 'reply'. I depicted it on Sequence Diagram here
> http://docs.google.com/Doc?docid=dgpvsb45_13fsmp45gc&hl=en.
> Problem highlighted with red.

Hi Axyd,

sorry, it's my fault. Your participant shouldn't reply to the engine
(I didn't think about that and was using BlockParticipant (Block as in
Ruby block of code, not blocking/stopping), which implicitely replies
to the engine. So you got it right by not using BlockParticipant and
not replying to the engine. Well done !

Calling reply lets the process continue, it's important not to reply
since you're waiting for answer from the real participant.

About the "not releasing" : the consume method should immediately exit
when it's done sending. The thread will be released as soon as the
consume method exits :

http://github.com/jmettraux/ruote/blob/8a154653e7eda997dfe83eeb21f6bc3b08d7e6ee/lib/openwfe/participants/participant_map.rb#L179

Once the participant has "consumed" the workitem, the engine is
supposed to sit and wait. Maybe what you experience as "doesn't
release its thread" is simply "the engine doesn't move until the reply
comes" which is the intended behaviour.


> The code for Sample (if you will be interested) is here:
> async_participant.rb http://docs.google.com/Doc?docid=dgpvsb45_10fm69kxhg&hl=en
> definitions.rb http://docs.google.com/Doc?docid=dgpvsb45_9ct4sdjgx&hl=en
> question.rb http://docs.google.com/Doc?docid=dgpvsb45_11dpxg5vd4&hl=en
> answer.rb http://docs.google.com/Doc?docid=dgpvsb45_12g7b2cvcj&hl=en
>
> First runs 'question.rb', prints the question on console and then
> exits.

> Then runs 'answer.rb', restores Engine from disk, and waits for user


> input on the console, then passes it to Engine.
>
> Should i call 'reply' twice (on send and on receive)? Or there is
> another way to release Thread? Or it's ok with it?

You should call once and only once (at receive time).

Your code looks good, I hope you're having fun implementing all of this.

Axyd

unread,
Mar 28, 2009, 4:08:29 PM3/28/09
to Ruote (OpenWFEru) users
Hi John, finally i got the idea, thanks for help :).

A little suggestion for improving docs.
The understanding come to me after examining ArParticipant and ruote-
web2 code. I'm not using Rails so i don't look at it first.
Maybe it's worth to include a little notation about consume/reply
mechanism in docs/tutorials? Now docs using only BlockParticipants and
really important mechanism of 'consume/reply' is absolutely invisible
behind it. It's not obvious how it works.

It's not a complaint, docs are good! Just a little suggestion :).

John Mettraux

unread,
Mar 28, 2009, 11:18:22 PM3/28/09
to openwfe...@googlegroups.com
On Sun, Mar 29, 2009 at 5:08 AM, Axyd <axy...@gmail.com> wrote:
>
> Maybe it's worth to include a little notation about consume/reply
> mechanism in docs/tutorials? Now docs using only BlockParticipants and
> really important mechanism of 'consume/reply' is absolutely invisible
> behind it. It's not obvious how it works.
>
> It's not a complaint, docs are good! Just a little suggestion :).

Hi Axyd, thanks for the suggestion, I will write something about that,
you are right.

John Mettraux

unread,
Apr 12, 2009, 6:17:04 AM4/12/09
to openwfe...@googlegroups.com
On Sun, Mar 29, 2009 at 12:18 PM, John Mettraux <jmet...@openwfe.org> wrote:
> On Sun, Mar 29, 2009 at 5:08 AM, Axyd <axy...@gmail.com> wrote:
>>
>> Maybe it's worth to include a little notation about consume/reply
>> mechanism in docs/tutorials? Now docs using only BlockParticipants and
>> really important mechanism of 'consume/reply' is absolutely invisible
>> behind it. It's not obvious how it works.
>>
>> It's not a complaint, docs are good! Just a little suggestion :).
>
> Hi Axyd, thanks for the suggestion, I will write something about that,
> you are right.

Hi Axyd, hi all,

I've started a piece of documentation at :

http://openwferu.rubyforge.org/part.html

feel free to comment / critique it here. The part on remote
participants / listeners is still a TODO.


Thanks again,

Reply all
Reply to author
Forward
0 new messages