On Tue, Jul 17, 2012 at 07:58:08PM -0700, jordi wrote:
>
> We are using Ruote inside a web service that needs to answer to its users
> if its job (implemented as a workflow) has finished correctly or not.
>
> Using engine.process(wfid) we get information about this wfid so we tell
> the users when the process is running or had some error.
>
> The problem is that we can not distinguish between a wfid that we have
> never run (an incorrect wfid) and a wfid that passed through the system and
> finished already (it seems that Ruote forgets about finished wfids)
Hello Jordi,
welcome to the ruote mailing list.
Ruote behaves a bit like an operating system. You run processes, they have
PIDs and when they terminate, well the PID points to nothing (or to a new
process). Unlike an operating system, ruote (at least its most common wfid
generation routines) don't re-use wfids (provided the clocks are not wrong).
Unfortunately, it means it's up to you to do the gone process / wfids
accounting.
> I think this is a common issue to have and surely there is a best practice
> on how to manage this situation but I have not found anything relevant in
> this mailing list.
> What's the best way to handle this situation?
I don't know the details of your ruote use so I cannot tell you what is the
best way. If I knew the details, I'd probably say something that is off and
wrong anyway (I'm an average human with a small head).
Let's enumerate a few variants to help you pick one.
== the logger
Let's use the default logger, it keeps track of the last 147 msgs, maybe it
still knows about the process instance.
#engine = Ruote::Engine.new(...) # old style
dashboard = Ruote::Dashboard.new(...)
class << dashboard
def status(wfid)
if ps(wfid)
"RUNNING"
elsif logger.log.find { |msg| msg['wfid'] == wfid }
"DONE"
else
"UNKNOWN" # never ran or was forgotten
end
end
end
Disadvantages:
* It really forgets after a while
* Only works for the "local" work (it doesn't work in multi-worker setups)
== the history
By default, ruote has a in-memory history service running, much like the
logger above, but it tracks the last 1000 msgs. Like the logger, it's only
local to a worker, so it doesn't work in multi-worker setups.
But you can setup a Ruote::StorageHistory to keep track of history in the
storage (so if you use ruote-sequel with PostgreSQL, the history will end up
in that database).
Use example:
https://github.com/jmettraux/ruote/blob/e5996817d09313ebc19b5586dbc9671f99d55420/test/functional/ft_36_storage_history.rb
We could thus write:
dashboard = Ruote::Dashboard.new(...)
dashboard.add_service(
'history', 'ruote/log/storage_history', 'Ruote::StorageHistory')
class << dashboard
def status(wfid)
if ps(wfid)
"RUNNING"
elsif context.history.by_wfid(wfid)
"DONE"
else
"NONE"
end
end
end
Disadvantages:
* It stores the whole history for all the processes (unless you provide an
alternate implementation that only stores when process terminates)
== the on_terminate registry
Write a ruote service that observes termination and persists terminated
wfids.
It'd look like:
dashboard = Ruote::Dashboard.new(...)
class Acme::Observer
def initialize(context, options={})
end
def on_msg(msg)
next unless msg['action'] == 'terminated'
$database.terminated_wfids << msg['wfid']
end
end
dashboard.add_service('observer', Acme::Observer)
class << dashboard
def status(wfid)
if ps(wfid)
"RUNNING"
elsif $database.terminated_wfids.include?(wfid)
"DONE"
else
"NONE"
end
end
end
== ???
There is probably a better solution, adapted to your system and so on...
I've seen other approaches where people do no polling at all and immediately
notify clients of terminated processes.
I hope it'll help. Best regards,
--
John Mettraux - http://lambda.io/jmettraux
--
you received this message because you are subscribed to the "ruote users" group.
to post : send email to [email protected]
to unsubscribe : send email to [email protected]
more options : http://groups.google.com/group/openwferu-users?hl=en