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