Hello list,

I'm thinking about deprecating "stateful" participants, ie participants that 
are registered as instances instead of as classes.

  engine.register_participant 'alice', testParticipant

vs

  engine.register_participant 'alice', TestParticipant

There is some explanation about state{ful|less} at

  http://ruote.rubyforge.org/implementing_participants.html

but it's light.


Since ruote 2.1.x has potentially multiple workers in different Ruby runtimes, 
memory is not shared, especially participant and instance variables, and blocks 
of code (procs). Ruote currently has an exception built in for "stateful 
participants" registered, it ensures the local worker deals with those 
participants (well other workers simply can't).


The most common "stateful participant" is the BlockParticipant :

---8<---
  engine.register_participant 'alice' do |workitem|
    workitem.fields['x'] = y
  end
--->8---

as the block only exists in the Ruby runtime where the register_participant is 
run, workers in other runtimes can't deal with workitems for the alice 
participant.

the generic "stateful participant" might look like :

---8<---
  class MyParticipant
    def initialize(opts)
      @opts = opts
      @seen = []
    end
    def consume(workitem)
      workitem.fields['colour'] = @opts[:colour]
      @seen << workitem.fei.to_s
      reply_to_engine(workitem)
    end
    def cancel(fei, flavour)
      # do nothing
    end
  end

  red = MyParticipant.new(:colour => 'red')
  green = MyParticipant.new(:colour => 'green')

  engine.register_participant 'ray', red
  engine.register_participant 'greg', green
--->8---

The participant is 'stateful', it keeps a @seen instance variable which is not 
sharable among Ruby runtimes.

I'd like to deprecate such stateful participants for ruote 2.1.12 and remove 
support for them completely for ruote 2.1.13.

The right way to implement the above MyParticipant is

---8<---
  class MyParticipant
    def initialize(opts)
      @opts = opts
    end
    def consume(workitem)
      workitem.fields['colour'] = @opts[:colour]
      store(workitem.fei.to_s)
      reply_to_engine(workitem)
    end
    def cancel(fei, flavour)
      # do nothing
    end
    def store(info)
      open_db(@opts[:db]).store(info)
        # some pseudo db lib call
    end
  end

  engine.register_participant 'ray', MyParticipant, :colour => 'red', :db => 'x'
  engine.register_participant 'greg', MyParticipant, :colour => 'green', :db => 
'x'
--->8---

The options passed at registration must be JSON-serializable so that any worker 
that has access to the MyParticipant class can instantiate such a participant 
and hand work to it.


You'll say : right, but how about the block participant ?

I will experiment with "sourcify" and serialize the participant's block

  https://github.com/ngty/sourcify

So that the block may travel from one ruby runtime to the next.

I'll certainly put the same security checks I have for Ruby process definitions 
and ${ruby:execute that code} on the block :

  
https://github.com/jmettraux/ruote/blob/2669b1886a6419e307bea889842262610f090432/lib/ruote/svc/treechecker.rb#L42-84

There is a catch, closures will not be possible

---8<---
  counter = 0

  engine.register_participant 'increment' do |workitem|
    counter = counter + 1
  end
--->8---

Serialized block participants won't take the counter in the fridge (storage) 
with them.


Any questions/comments/critiques/suggestions/feedback ? Any green lights ?

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



P.S. I wrote a blog post about switch/case/given and ruote the other day, it's 
at :

  http://jmettraux.wordpress.com/2011/01/03/ruote-and-switch/

-- 
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