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

Reply via email to