Coder Social home page Coder Social logo

ruote's Introduction

Important Note

Active development on ruote ceased.

See scaling down ruote.

Do not involve ruote in your new project.

** 2016-12-12 Update **

Ruote development moved to a new Ruby workflow engine named flor.

The team is named floraison and there is also a "flor behind Rack" project named flack.

ruote

Ruote is a Ruby workflow engine. It's thus a workflow definition interpreter. If you're enterprisey, you might say business process definition.

Instances of these definitions are meant to run for a long time, so Ruote is oriented towards persistency / modifiability instead of transience / performance like a regular interpreter is. A Ruote engine may run multiple instances of workflow definitions.

Persistent mostly means that you can stop Ruote and later restart it without losing processes. Modifiability means that you can modify a workflow instance on the fly.

Process definitions are mainly describing how workitems are routed to participants. These participants may represent worklists for users or group of users, pieces of code, ...

usage

grab ruote

gem install yajl-ruby
gem install rufus-scheduler -v 2.0.24
gem install ruote

or better, use a Gemfile like this one: https://gist.github.com/jmettraux/22f24fca70c5a116b01c

Then

require 'rubygems'
require 'ruote'
require 'ruote/storage/fs_storage'

# preparing the engine

engine = Ruote::Engine.new(
  Ruote::Worker.new(
    Ruote::FsStorage.new('ruote_work')))

# registering participants

engine.register_participant :alpha do |workitem|
  workitem.fields['message'] = { 'text' => 'hello !', 'author' => 'Alice' }
end

engine.register_participant :bravo do |workitem|
  puts "I received a message from #{workitem.fields['message']['author']}"
end

# defining a process

pdef = Ruote.process_definition :name => 'test' do
  sequence do
    participant :alpha
    participant :bravo
  end
end

# launching, creating a process instance

wfid = engine.launch(pdef)

engine.wait_for(wfid)
  # blocks current thread until our process instance terminates

# => 'I received a message from Alice'

test suite

see http://github.com/jmettraux/ruote/tree/master/test

license

MIT

links

feedback

ruote's People

Contributors

adrienkohlbecker avatar coffeeaddict avatar denisahearn avatar dependabot[bot] avatar doitdistributed avatar ironmann avatar jmettraux avatar kennethkalmer avatar maxgfeller avatar netinlet avatar npj avatar p avatar pepe avatar vjt avatar xtr3me avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ruote's Issues

Engine#add_service issue

from http://groups.google.com/group/openwferu-users/t/1ac2adca35c0e3c9

2.) Our workers get started via a daemon, we are also using ruote-
sequel and Ruote-kit. When we try and call

RuoteKit.engine.add_service( 'history', 'ruote/log/storage_history',
'Ruote::StorageHistory')

It does not seem to properly register the service or the service
seems like it is getting overwritten by the DefaultHistory.The
context.notify never calls StorageHistory.notify. But I have seen the
service gets registered.

When I add the service via Ruote::Context.default_conf everything
works correctly.>
Should the service be register from the worker or when the engine is
initialized or both? I have tried both with no effect.

engine breaks when encountering corrupt data

C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/expool/fs_exps
torage.rb:222:in `load': marshal data too short (ArgumentError)
        from C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/e
xpool/fs_expstorage.rb:222:in `load_fexp'
        from C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/e
xpool/fs_expstorage.rb:220:in `open'
        from C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/e
xpool/fs_expstorage.rb:220:in `load_fexp'
        from C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/e
xpool/fs_expstorage.rb:150:in `find_expressions'
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `in
ject'
        from C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/e
xpool/fs_expstorage.rb:148:in `each'
        from C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/e
xpool/fs_expstorage.rb:148:in `inject'
        from C:/ruote/ruote-web2/vendor/plugins/ruote_plugin/lib_ruote/openwfe/e
xpool/fs_expstorage.rb:148:in `find_expressions'
         ... 22 levels...
        from c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.2/lib/commands/server.rb:8
4
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `ge
m_original_require'
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `re
quire'
        from script/server:3

:limit option is not working properly with by_participant and query on fs_storage

When I invoke

RuoteKit.engine.storage_participant.query({:participant_name
=> 'bob', :skip => 0, :limit => 10})
or
RuoteKit.engine.storage_participant.by_participant('bob',
{:skip => 0, :limit => 10})
using fs_storage I get <= 10 results per chunk instead of 10 results per chunk. Having list of bob workitems larger than 10. It is so due to limit being passed down to storage while participants are filtered later. In by_participants it is done so:

        res = fetch_all(opts).select { |wi|
          wi['participant_name'] == participant_name
        }

And in query:

      hwis = wfid ?
 @context.storage.get_many('workitems', wfid, opts) : fetch_all(opts)

 return hwis unless hwis.is_a?(Array)

 hwis = hwis.select { |hwi|
   Ruote::StorageParticipant.matches?(hwi, pname, cr)
 }

The list returned from fetch_all(opts) is always of a size 10 but it is filtered after being returned from fs_storage hence resulting list is <= 10.

undefined method `match' for <URI::

i write my subprocess like this

then the error appear "undefined method match...."
def read_uri (uri)

return File.read(uri) if uri.match(/^[a-zA-Z]:[/]/)

  if uri.is_a?(String) and uri.match(/^[a-zA-Z]:[\/\\]/)
    return File.read(uri)
  end
    # seems like we're on windows, well... A:/ ?
  u = URI.parse(uri.to_s)
  raise(':remote_definitions_allowed is set to false') \
    if (ac[:remote_definitions_allowed] != true and
      u.scheme and
      u.scheme != 'file')
  f = Rufus::Verbs.fopen(u) # Rufus::Verbs is OK with redirections
  result = f.read
  f.close if f.respond_to?(:close)
  result
end

here is the code i had change

ruote-couch / rufus-jig NoMethodError

test/functional_eft_28_once.rb

line 91~

noisy /Users/jmettraux/w/ruote/test/functional/base.rb:38:in `setup'
0 60 pa *  {"regex"=>"alpha", "engine_worker_only"=>true}
1 60 la * 20110114-bimehinibe {:wi=>["0!b7d0045d5c6417cf03214d3ed66d5bf8!20110114-bimehinibe", 0], :t=>["define", {}, [["as_soon_as", {"true"=>nil, "freq"=>"10d"}, [["alpha", {}, []]]]]]}
2 60     er * 20110114-bimehinibe f0ae9 0_0
20110114-bimehinibe NoMethodError
20110114-bimehinibe undefined method `match' for nil:NilClass
20110114-bimehinibe /Users/jmettraux/.rvm/gems/ruby-1.9.2-p136/gems/rufus-jig-1.0.0/lib/rufus/jig/path.rb:84:in `to_path'
20110114-bimehinibe /Users/jmettraux/.rvm/gems/ruby-1.9.2-p136/gems/rufus-jig-1.0.0/lib/rufus/jig/path.rb:68:in `block in join'
20110114-bimehinibe /Users/jmettraux/.rvm/gems/ruby-1.9.2-p136/gems/rufus-jig-1.0.0/lib/rufus/jig/path.rb:66:in `collect'
20110114-bimehinibe /Users/jmettraux/.rvm/gems/ruby-1.9.2-p136/gems/rufus-jig-1.0.0/lib/rufus/jig/path.rb:66:in `join'
20110114-bimehinibe /Users/jmettraux/.rvm/gems/ruby-1.9.2-p136/gems/rufus-jig-1.0.0/lib/rufus/jig/couch.rb:473:in `adjust'
20110114-bimehinibe /Users/jmettraux/.rvm/gems/ruby-1.9.2-p136/gems/rufus-jig-1.0.0/lib/rufus/jig/couch.rb:92:in `get'
20110114-bimehinibe /Users/jmettraux/w/ruote-couch/lib/ruote/couch/database.rb:63:in `get'
20110114-bimehinibe /Users/jmettraux/w/ruote-couch/lib/ruote/couch/storage.rb:102:in `get'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/storage/base.rb:187:in `delete_schedule'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/exp/fe_once.rb:167:in `reply'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/exp/fe_once.rb:154:in `apply'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/exp/flowexpression.rb:228:in `do_apply'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/worker.rb:307:in `launch'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/worker.rb:219:in `process'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/worker.rb:164:in `step'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/worker.rb:73:in `run'
20110114-bimehinibe /Users/jmettraux/w/ruote/lib/ruote/worker.rb:85:in `block in run_in_thread'

Per field merge strategy

It could be interesting to have a merge strategy per field. We needed this in one of our projects, so we had to manually get all the outputs and merge that specific field manually. It looked very cumbersome and eventually we fell back to a non concurrent iterator.

Any thoughts on that?

:count option handling in StorageParticipant#[all,by_participant,query]

When invoked with {:count => true} methods all and by_participant will fail and query will return wrong numbers when using both :count and :participant {:count => true, :participant => "bob"}.
With all it's simply a meter of one "if" there is:


fetch_all(opts).map { |hwi| Ruote::Workitem.new(hwi) }

and should be something like:


if opts[:count]
  return fetch_all(opts).map { |hwi| Ruote::Workitem.new(hwi) }
else
  return fetch_all(opts)
end

and same for by_participant last line is:


hwis.collect { |hwi| Ruote::Workitem.new(hwi) }

and should be like:


if opts[:count]
  return hwis.collect { |hwi| Ruote::Workitem.new(hwi) }
else
  return hwis
end

But with query I don't really now how to fix it. For some reason it is not passing :participant to storage engine so the count comes totally wrong. One option is to remove :count from the list and count is manually (performance will by bad) another is to pass somehow :participant argument down to the storage.

Nested forget after rewind

Hi John,

Gotta another curveball for you. I haven't been able to get the test to display the issue I'm having correctly but hopefully there's enough here to give you an idea of what's going on.

Basically, I have "sub2" that I always want to forget and "possibly_start_over" which is a participant that determines if the cursor should be rewinded. In my production workflow, when "possibly_start_over" issues the "rewind" command, the workflow does not actually forget "sub2" - it still waits for it. But when I change the command to "reset", the workflow proceeds to "charly" as expected, forgetting "sub2".

Any ideas? Or can I give you more information?

Thanks,
Chris

  def test_nested_forget_after_rewind
    pdef = Ruote.process_definition do
      define "sub1" do
        cursor do
          apply
          sub2 :forget => true
          bravo
        end
      end

      define "sub2" do
        cursor do
          alpha
        end
      end

      cursor :tag => "main" do
        sub1
        possibly_start_over
      end

      charly
    end

    alpha = @dashboard.register_participant :alpha, Ruote::StorageParticipant
    bravo = @dashboard.register_participant :bravo, Ruote::StorageParticipant
    charly = @dashboard.register_participant :charly, Ruote::StorageParticipant
    possibly_start_over = @dashboard.register_participant :possibly_start_over, Ruote::StorageParticipant

    wfid = @dashboard.launch(pdef)

    wait_for(:bravo)
    wi = bravo.first
    @dashboard.reply(wi)

    wait_for(:possibly_start_over)
    wi = possibly_start_over.first
    wi.fields["__command__"] = "rewind" # Will still wait for sub2
    # wi.fields["__command__"] = "reset" # Though resetting forgets sub2 as expected
    @dashboard.reply(wi)

    wait_for(:bravo)
    wi = bravo.first
    @dashboard.reply(wi)

    wait_for(:possibly_start_over)
    wi = possibly_start_over.first
    @dashboard.reply(wi)

    wait_for(:charly)
  end

Registering participants: when put fails redoing registration fails

/gems/ruby/1.8/gems/ruote-2.1.11/lib/ruote/svc/participant_list.rb:85:in `register': wrong number of arguments (5 for 4) (ArgumentError)
from /gems/ruby/1.8/gems/ruote-2.1.11/lib/ruote/svc/participant_list.rb:85:in `register'
from /gems/ruby/1.8/gems/ruote-2.1.11/lib/ruote/engine.rb:485:in `register_participant'

Comparison between FlowExpressions subclasses sometimes fail.

I've seen it happen on instantiation of `` fetching the list of processes from the engine, so a call like:

engine.ps('some-wfid')

Would raise an exception similar to the ff:

ArgumentError: comparison of Ruote::Exp::SequenceExpression with Ruote::Exp::ParticipantExpression failed

I've traced it to the following line in ProcessStatus class initialization (starting from the ps method call):

# lib/ruote/engine/process_status.rb:66
@expressions.sort! { |a, b| a.fei.expid <=> b.fei.expid }

If a and b are different subclasses of FlowExpressions (eg: SequenceExpression vs ParticipantExpression) it's possible that the values returned by the calls tofei.expid will be of different types (eg: String vs Fixnum)

test_remote_definitions_allowed fails

  1) Failure:
test_remote_definitions_allowed(FtProcessDefinitionTest) [./test/functional/ft_22_process_definitions.rb:43]:
<[SocketError, OpenURI::HTTPError, ArgumentError]> exception expected but none was thrown.

Am I missing some pre-requirement?

better error messages when invalid process definitions

mostly when

engine.launch("toto.rb")

chat :

17:16 lbt: jmettraux: good morning....  when there is a mistake in a multi-line string imported process it just throws a   #<ArgumentError: failed to read processs definition of class String>
17:17 jmettraux: hello, radial ?
17:18 lbt: no, normal ruby-ish
17:19 lbt: usually I'm missing a 'do' or an 'end'    maybe a "," between params
17:19 jmettraux: OK
17:20 lbt: is it supposed to indicate the parse-error location ?
17:20 jmettraux: not yet
17:20 lbt expects jmettraux to never have noticed
17:20 jmettraux: you're right

worker#step should rescue

in development mode, it's important to catch errors in storage implementations and inform the developer about them.

NoMethodError: undefined method `rindex' for {}:Hash

Hi John,

Somewhere along the way, it looks like __tags__ is getting set to an empty hash in our workitems. We're storing workitems in Mongo outside of Ruote, so it may be that Mongoid/Mongo is converting the __tags__ value to a hash, but just wanted to ping you to see if you had any ideas where to look within Ruote that could be causing this, so I could try to get a test case prepared.

The error message and trace are below.

Thanks,
Chris

    message: #<NoMethodError: undefined method `rindex' for {}:Hash>
    trace:
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/workitem.rb:434:in `remove_tag'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/exp/flow_expression.rb:887:in `leave_tag'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/exp/flow_expression.rb:369:in `reply_to_parent'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/exp/fe_cursor.rb:268:in `move_on'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/exp/commanded.rb:53:in `reply'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/exp/flow_expression.rb:508:in `do_reply'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/exp/flow_expression.rb:301:in `do_action'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/worker.rb:330:in `process'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/worker.rb:212:in `step'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/worker.rb:93:in `run'
      /app/vendor/bundle/ruby/1.9.1/bundler/gems/ruote-d69981252e3d/lib/ruote/worker.rb:104:in `block in run_in_thread'

A bug of concurrence with :if conditions?

Hi John,

Thanks for fixing a concurrence :over_if bug a while back.

We now have more workflow definitions with concurrence, and I believe I've encountered a bug when :if conditions are involved. Below is a simple ruote process definition that illustrates the problem. Basically, there are concurrent participants with conditions.

In this case, entry labeled as 'step 2' would actually not participate, and if we complete 'step 1' with processed field set to 'yes'
we should expect to see 'step 3'. However in this case 'step 3' never shows up.

If I remove 'step 2' (because it does not participate anyway with the set condition), it works. If I leave 'step 3' as it is and take out the :if condition from 'step 3', then it also works.

Ruote.process_definition :name=>'mytest', :revision=>'1' do
sequence do
set :field=>"isok", :value=>"no"
set :field=>"processed", :value=>"no"
concurrence do
entry :task=>'step 1'
entry :task=>'step 2', :if=>"${f:isok} == yes"
end

entry :task=>'step 3', :if=>"${f:processed} == yes"

end
end

We have a set of helper methods (in our WorkflowSpecification module) to facilitate our rspec tests, and in this case, the test to show the bug looks like this (launch_workflow will load the above process_definition):

describe "Test Workflow" do
include WorkflowSpecification
before(:all){ prepare_environment_for :mytest, :entry, false }
after(:all) { cleanup_environment }
after(:each){ cancel_workflow }

it "shoudl work" do
launch_workflow
wi = expect_work_item "step 1"
complete_work_item "step 1", "processed"=>"yes"
expect_work_item 'step 3' # <=============== this never shows up
end
end

I wish I could quickly translate this little rspec test into a Test::Unit::TestCase test so you could quickly verify the case.

We are still using forked ruote (version 2.2.1) because we are not ready to move on to newer version yet, but I think it's a problem not specific to a version. I'd appreciate it if you could verify that it's case.

Thanks very much,
Alex

Internal Server Error on '_ruote/processes'

Hi, I was cancelling some old/hanging processes one by one via the Ruote admin interface. This went without any problems for a while until I ended up with an 'Internal Server Error' ... I was not in full concentration when making the 'killer' click, but I do not think I did anything different than the previous 30 or so processes I had cancelled:

  • click on the wfid link of one of the processes
  • click on the 'cancel' button

The top of the stack trace shows:

NoMethodError - private method `select' called for nil:NilClass:
 /usr/local/lib/ruby/gems/1.9.1/gems/ruote-2.2.0/lib/ruote/engine/process_status.rb:130:in `tags'
 /usr/local/lib/ruby/gems/1.9.1/gems/ruote-kit-2.2.0.3/lib/ruote-kit/views/processes.html.haml:47:in `block (2 levels) in singletonclass'
 /usr/local/lib/ruby/gems/1.9.1/gems/ruote-kit-2.2.0.3/lib/ruote-kit/views/processes.html.haml:31:in `each'
 /usr/local/lib/ruby/gems/1.9.1/gems/ruote-kit-2.2.0.3/lib/ruote-kit/views/processes.html.haml:31:in `block in singletonclass'
 /usr/local/lib/ruby/gems/1.9.1/gems/ruote-kit-2.2.0.3/lib/ruote-kit/views/processes.html.haml:65530:in `instance_eval'
 /usr/local/lib/ruby/gems/1.9.1/gems/ruote-kit-2.2.0.3/lib/ruote-kit/views/processes.html.haml:65530:in `singletonclass'
 /usr/local/lib/ruby/gems/1.9.1/gems/ruote-kit-2.2.0.3/lib/ruote-kit/views/processes.html.haml:65528:in `__tilt_81236760'

I can work around this by doing something like:
_ruote/processes?limit=100&skip=14 ...

Database gets refresh and all entries goes off

Hi i am using two rules to implement workflow i dont know why my data gets refresh automatically and all the entries of documents table get truncate

and only this remains in the table

"engine";"1";"configurations";"{"_id":"engine","type":"configurations","_rev":1,"put_at":"2012-05-09 06:32:10.714817 UTC"}";"";""

Can anybody help me to resolve this

attach reason and messages when timeout happens

I have following code:

pdef = Ruote.process_definition do 
  sequence :on_error=>:error_report do 
    alpha :id => "alpha", :timers => "1s: reminder, 2s:error" 
    bravo :id => "bravo" 
  end 
end 

(...)

my intentions are:

  1. in 1 sec send a reminder to alpha

  2. in 2 sec, cancel the process and the "error_report" handler comes in to
    do the housekeeping work.

    The problem is:
    When I say "item.error.inspect" in the error_report handler, it gives
    me: "class"=>"Ruote::ForcedError", "message"=>"error triggered from process
    definition". Which is not helpful when I want to know that the error is
    triggered by a timeout from alpha

Can we have the reason and messages attached when timeout happens?

/tmp/ruote_mailtrap.txt should be at least per-user

In a situation where multiple unix users on the same machine run the test suite, all users attempt to write to /tmp/ruote_mailtrap.txt which only works for the first user.

Scoping the file to a subdirectory of /tmp named for the running user is one possible solution, alternatives being to name the scope subdirectory after process id (permitting multiple concurrent test suite runs by the same user) or to name it randomly.

history : missing reply to concurrence

7:33 juris: btw one other thing. something we noticed about tasks defined in concurrence blocks
07:34 juris: when parsing history, it doesn't seem like the 'reply' for the last task to exit the block is ever received...
07:38 jmettraux: juris: maybe it's received after the reply to the concurrence
07:38 jmettraux: kellyp: hello and welcome to #ruote
07:40 juris: would it still be registered in the history with an action == 'reply' ?
07:40 jmettraux: kellyp: glad to read that
07:40 jmettraux: juris: if you see other "reply" then yes, any attributes set on your "concurrence" ?
07:50 juris: we pull all the entries that are action =~ /reply|dispatch/ - we do set some variables within those tasks in the concurrence
07:50 juris: (is that what you meatn by attributes?)
07:51 jmettraux: sorry, I meant "concurrence do" vs "concurrence :count => 1, :remaining => :forget do"
07:51 jmettraux: attributes of the expression
07:51 juris: ah... one of them we do:
07:51 juris: concurrence :merge_type => :mix, :over_if => '${issue}', :count => 2 do
07:53 jmettraux: by default, the remaining branches get cancelled, I'd have to double check, but they might not reply (especially since the concurrence is over and gone)
07:54 jmettraux: :count => 2 means that after 2 replies, the concurrence is over
07:54 jmettraux: :over_if => ... could terminate the concurrence even sooner
07:55 juris: so that means they wont have an entry in history?
07:56 jmettraux: it means the reply of the remaining branches to the gone concurrence won't make it in the history
07:56 juris: what we're seeing is that the reply of the task that causes the exit from the concurrence block does happen. it's just that
07:57 jmettraux: that's the right behaviour
07:57 juris: it does not seem like there is a history entry for it.

env : ruote 2.1.11

Breaking out of nested cursor in subprocess block

I'm having some trouble with breaking out to a main cursor from within a cursor in a subprocess block. I've set up two test cases to illustrate what's going on below. Am I trying to do something unsupported/wacky or would you expect both of these test cases to pass?

Thanks!
Chris

  def test_nested_break_passes
    pdef = Ruote.process_definition do
      define "sub1" do
        # do some stuff
        apply # apply isn't in a new cusor - process works fine
        #do some more stuff
      end

      cursor :tag => "main" do
        sub1 do
          bravo
        end
        sub1 do
          alpha
        end
      end

      charly
    end

    alpha = @dashboard.register_participant :alpha, Ruote::StorageParticipant
    bravo = @dashboard.register_participant :bravo, Ruote::StorageParticipant
    charly = @dashboard.register_participant :charly, Ruote::StorageParticipant


    wfid = @dashboard.launch(pdef)
    wait_for(:bravo)
    wi = bravo.first
    wi.fields['__command__'] = [ 'break', "main" ]

    @dashboard.reply(wi)
    wait_for(:charly)
  end

  def test_nested_break_hangs
    pdef = Ruote.process_definition do
      define "sub1" do
        cursor do
          # do some stuff
          apply # apply is now nested in a cursor
          # do some more stuff
        end
      end

      cursor :tag => "main" do
        sub1 do
          bravo
        end
        sub1 do
          alpha
        end
      end

      charly
    end

    alpha = @dashboard.register_participant :alpha, Ruote::StorageParticipant
    bravo = @dashboard.register_participant :bravo, Ruote::StorageParticipant
    charly = @dashboard.register_participant :charly, Ruote::StorageParticipant


    wfid = @dashboard.launch(pdef)
    wait_for(:bravo)
    wi = bravo.first
    wi.fields['__command__'] = [ 'break', "main" ]

    @dashboard.reply(wi)
    wait_for(:charly)
  end

support variable number of arguments in participant_list

when use Rufus::Decision::Participant I was getting "'table' option is missing"
ruby -v
ruby 1.8.7 (2010-06-23 patchlevel 299) [i686-linux]

original code in lib/ruote/svc/participant_list.rb
pa = if pa_class.instance_method(:initialize).arity > 0
pa_class.new(options)
else
pa_class.new
end
changed to be
pa = if pa_class.instance_method(:initialize).arity == 0
pa_class.new
else
pa_class.new(options)
end
This handles the case where arguments are specified as optional or with defaults.

Engine#wait_for(wfid) hangs if workflow finished before the call

Consider the following scenario:

  1. Create a workflow that executes quickly, for example calls a missing method right away, thus terminating with an error almost immediately after the launch
  2. Launch this workflow with Engine#launch, store wfid
  3. Do something else such as sleep(2), so that the workflow runs and terminates
  4. Wait for the workflow with Engine#wait_for

What appears to happen is the program hangs, I guess because wait_for waits for an event referencing the wfid which will never happen since workflow is finished.

This behavior makes wait_for rather unusable.

functional/eft_18_concurrent_iterator test hangs

Most of the times when I run this test it hangs and the ruby process is not interruptible via Ctrl-C and also not killable via kill (ignores SIGTERM).

One time I managed to receive a stack trace:

/home/rm/apps/ruote/lib/ruote/log/test_logger.rb:93:in `stop': Interrupt
from /home/rm/apps/ruote/lib/ruote/log/test_logger.rb:93:in `wait_for'
from /home/rm/apps/ruote/lib/ruote/engine.rb:239:in `wait_for'
from ./functional/base.rb:101:in `wait_for'
from ./functional/base.rb:69:in `assert_trace'
from ./functional/eft_18_concurrent_iterator.rb:281:in `test_merge_type_isolate'
from /usr/local/lib/ruby/1.8/test/unit/testcase.rb:78:in `__send__'
from /usr/local/lib/ruby/1.8/test/unit/testcase.rb:78:in `run'
from /usr/local/lib/ruby/1.8/test/unit/testsuite.rb:34:in `run'
from /usr/local/lib/ruby/1.8/test/unit/testsuite.rb:33:in `each'
from /usr/local/lib/ruby/1.8/test/unit/testsuite.rb:33:in `run'
from /usr/local/lib/ruby/1.8/test/unit/testsuite.rb:34:in `run'
from /usr/local/lib/ruby/1.8/test/unit/testsuite.rb:33:in `each'
from /usr/local/lib/ruby/1.8/test/unit/testsuite.rb:33:in `run'
from /usr/local/lib/ruby/1.8/test/unit/ui/testrunnermediator.rb:46:in `run_suite'
from /usr/local/lib/ruby/1.8/test/unit/ui/console/testrunner.rb:67:in `start_mediator'
from /usr/local/lib/ruby/1.8/test/unit/ui/console/testrunner.rb:41:in `start'
from /usr/local/lib/ruby/1.8/test/unit/ui/testrunnerutilities.rb:29:in `run'
from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:216:in `run'
from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:12:in `run'
from /usr/local/lib/ruby/1.8/test/unit.rb:279
from test.rb:9

This happens when I run ruby test.rb or ruby functional/eft_18_concurrent_iterator.rb.

This is on: ruby 1.8.7 (2009-12-24 patchlevel 248)

LoadError when running tests and patron gem not installed

/ruote$ ruby test/test.rb 
ruby 1.8.7 i686-linux
/opt/ruby-enterprise/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- patron (LoadError)
from /opt/ruby-enterprise/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from ./test/unit/ut_17_storage.rb:13
from ./test/unit/test.rb:8:in `load'
from ./test/unit/test.rb:8
from ./test/unit/test.rb:8:in `each'
from ./test/unit/test.rb:8
from test/test.rb:8:in `load'
from test/test.rb:8

treechecker shouldn't choke on IOError and other classes

22:03 _Taz_: Is there a way to handle "being / rescue / end" block without being shot at by the Rufus tree Checker about global vars?
22:04 jmettraux: ?
22:05 jmettraux: begin/rescue/end has nothing to do with global variables 
22:06 _Taz_: Event with a "rescue IOError => e [...]", with IOError being considered as a global var?
22:07 jmettraux: what is the exact error message you are seeing ?
22:08 _Taz_: /var/lib/gems/1.8/gems/rufus-treechecker-1.0.6/lib/rufus/treechecker.rb:238:in `check': global vars are forbidden (Rufus::SecurityError)
22:08 _Taz_: from /var/lib/gems/1.8/gems/rufus-treechecker-1.0.6/lib/rufus/treechecker.rb:519:in `do_check'
22:08 _Taz_: from /var/lib/gems/1.8/gems/rufus-treechecker-1.0.6/lib/rufus/treechecker.rb:525:in `do_check'
22:08 _Taz_: [... truncated ...]
22:08 _Taz_: from /var/lib/gems/1.8/gems/ruote-2.2.1/lib/ruote/engine.rb:622:in `register_participant'
22:08 _Taz_: from ./rest.rb:334

Exception when ruote tries to cancel workflow

I'm working on isolating the failure but it started happening after I added :on_error handlers. My process definition looks like this:

participant :mark_started
sequence :on_error => :mark_failed do
  participant :bogus
end
participant :mark_finished

mark_failed never runs, instead I get this exception on master:

== worker intercepted error ==

#<NoMethodError: undefined method `match' for nil:NilClass>
../../ruote/lib/ruote/part/participant_list.rb:154:in `lookup_info'
/usr/local/lib/ruby/gems/1.8/gems/rufus-cloche-0.1.17/lib/rufus  /cloche.rb:301:in `find'
../../ruote/lib/ruote/part/participant_list.rb:154:in `each'
../../ruote/lib/ruote/part/participant_list.rb:154:in `find'
../../ruote/lib/ruote/part/participant_list.rb:154:in `lookup_info'
../../ruote/lib/ruote/part/participant_list.rb:165:in `lookup'
../../ruote/lib/ruote/part/dispatch_pool.rb:60:in `dispatch_cancel'
../../ruote/lib/ruote/part/dispatch_pool.rb:48:in `handle'
../../ruote/lib/ruote/worker.rb:191:in `process'
../../ruote/lib/ruote/worker.rb:128:in `step'
../../ruote/lib/ruote/worker.rb:70:in `run'
../../ruote/lib/ruote/worker.rb:81:in `run_in_thread'
../../ruote/lib/ruote/worker.rb:81:in `initialize'
../../ruote/lib/ruote/worker.rb:81:in `new'
../../ruote/lib/ruote/worker.rb:81:in `run_in_thread'
../../ruote/lib/ruote/engine.rb:61:in `initialize'
[application backtrace snipped]

Debugging this I discovered that ParticipantExpression#cancel has h.participant_name set to nil here:

http://github.com/jmettraux/ruote/blob/ruote2.1/lib/ruote/exp/fe_participant.rb#L173

which eventually causes the exception above.

_if comparisons of fields with a : in the value fail

actual use:

Ruote.process_definition :name => 'try_equality' do
set 'project' => 'home:lbt:zDE:Trunk'
set 'final_project' => 'home:lbt:zDE:Trunk'
_if '${final_project} == ${project}' do
echo "Equal '${final_project} == ${project}'"
echo "Not Equal '${final_project} == ${project}'"
end
end

=>
Not Equal 'home:lbt:zDE:Trunk == home:lbt:zDE:Trunk'

actually: _if '${project} == ${project}' fails

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.