Implementing a ruote-based async web app using pub sub

39 views
Skip to first unread message

Reed Law

unread,
Feb 21, 2012, 11:45:38 AM2/21/12
to ruote
I am exploring using Ryan Bates' private_pub gem to allow the server
to send messages to clients about new workitems. The way I imagine it
working is that Ruote would send a message when a new workitem appears
to the user's browser which would then display the appropriate
template that allows the user to process that workitem.

I've looked at this thread:
http://groups.google.com/group/openwferu-users/browse_thread/thread/9159e802974f5aed/08d0047664f35cde

But I'm not sure how to implement this. When a user creates a new
paper, a workflow is launched in the controller. That workflow is then
run asynchronously while the controller sends its response
synchronously to the user. When the asynchronous ruote process
presents a workitem to the user participant, how can I get it to
launch--e.g. PrivatePub.publish_to "/messages/new", :workitem_message
=> "New task available." I don't want the workitem to be processed at
this point, just passed to the user for processing. I know I probably
need to implement a custom participant, I'm just a little unclear of
how that works in the context of a Rails app using Ruote-Kit. I've
looked at example participants such as the one in the thread above,
but I can't make out how they work.

Let me try to guess how a custom participant would work:
The #on_workitem method would call PrivatePub#publish_to with the
user's session id and new task.
#on_cancel would cancel the workitem, perhaps after a certain amount
of time had passed.
#on_reply would define what to do with the processed workitem before
continuing.
Then I would need to implement a receiver that would be called by the
controller when the user submits the processed workitem. How would
this receiver respond to the correct workitem? I assume that would be
defined by #workitem_from_msg in the example
http://ruote.rubyforge.org/implementing_participants.html#on_reply

John Mettraux

unread,
Feb 21, 2012, 3:23:06 PM2/21/12
to openwfe...@googlegroups.com

On Tue, Feb 21, 2012 at 08:45:38AM -0800, Reed Law wrote:
>
> I am exploring using Ryan Bates' private_pub gem to allow the server
> to send messages to clients about new workitems. The way I imagine it
> working is that Ruote would send a message when a new workitem appears
> to the user's browser which would then display the appropriate
> template that allows the user to process that workitem.
>
> (...)

>
> But I'm not sure how to implement this. When a user creates a new
> paper, a workflow is launched in the controller. That workflow is then
> run asynchronously while the controller sends its response
> synchronously to the user. When the asynchronous ruote process
> presents a workitem to the user participant, how can I get it to
> launch--e.g. PrivatePub.publish_to "/messages/new", :workitem_message
> => "New task available." I don't want the workitem to be processed at
> this point, just passed to the user for processing.

Hello Reed,

I don't think you need to implement the whole participant by yourself.

This should be sufficient:

---8<---
class ReedParticipant < Ruote::StorageParticipant

def on_workitem
super
PrivatePub.publish_to(
'/messages/new', :workitem_message => 'New task available.')
end
end
--->8---

It's the regular storage participant, it receives the workitem, stores in the
storage and then notifies the user thanks to PrivatePub.

In config/initializers/ruote-kit.rb you have to bind the participant names to
that participant:

---8<---
RuoteKit.engine.register do

participant 'user_.*', ReedParticipant
# all participant whose name start with 'user_' are notified

catchall Ruote::StorageParticipant
# no notifications for the rest
end
--->8---


> Let me try to guess how a custom participant would work:

OK, let's walk through those methods together.

> The #on_workitem method would call PrivatePub#publish_to with the
> user's session id and new task.

Yes, but in the ReedParticipant above we also store the workitem (thanks to
the Ruote::StorageParticipant parent class).

> #on_cancel would cancel the workitem, perhaps after a certain amount
> of time had passed.

#on_cancel is called when the flow the participant is in gets cancelled.
There are roughly three types of cancellation: deliberate cancellation (of
a workflow or of a part of it), timeout cancellation and rollback
cancellation (trigerred by an error handler).

> #on_reply would define what to do with the processed workitem before
> continuing.

Yes, it gives you an opportunity to tweak the workitem right before the
participant hands it back to the engine.


> Then I would need to implement a receiver that would be called by the
> controller when the user submits the processed workitem. How would
> this receiver respond to the correct workitem? I assume that would be
> defined by #workitem_from_msg in the example
> http://ruote.rubyforge.org/implementing_participants.html#on_reply

Yes, exactly. But as we've seen above, you don't seem to need a receiver at
all, you are merely adding a bell to the Ruote::StorageParticipant.


I hope it all makes sense, best regards,

--
John Mettraux - http://lambda.io/processi

Reed Law

unread,
Feb 21, 2012, 5:26:42 PM2/21/12
to ruote
This works beautifully! The workitem is created from a POST to the
create action and then almost instantaneously PrivatePub is sending
the js to the browser and updating the view. This makes for a very
smooth user experience when the views are updated with jQuery's fadeIn
and fadeOut. It feels like a traditional web app and the user never
has to know things are happening asynchronously. This will make multi-
step forms much easier to code and more RESTful.

John, thanks again for your help and I'm becoming a bigger fan of
Ruote every day!
Reply all
Reply to author
Forward
0 new messages