Hi Jason,
you first have to provide a class that implements a safe #generate
method (must return a String), like for example :
(NOTE : these examples are ruote 2.0 based)
---8<---
module MyRuote
class ArgoWfidGenerator
def generate
(Time.now.to_f * 1000).to_i.to_s
# probably not safe (not unique in a group of systems)
end
end
end
--->8---
Then you tell your engine about it :
---8<---
engine.add_service(:s_wfid_generator, MyRuote::ArgoWfidGenerator)
--->8---
or you work with an engine that overrides #build_wfid_generator :
---8<---
module MyRuote
class Engine < Ruote::FsPersistedEngine
def build_wfid_generator
add_service(:s_wfid_generator, MyRuote::ArgoWfidGenerator)
end
end
end
#...
engine = MyRuote::Engine.new(opts)
--->8---
Best regards,
--
John Mettraux - http://jmettraux.wordpress.com
Hi Jason,
this correct. The possible flavour are nil (regular cancel), :kill
(super cancel, no on-cancel allowed) and :timeout (a cancel resulting)
from a timeout.
The participant expression doesn't currently use this flavour
information, but now that you tell me about it I will pass the
information to the participant implementation.
Done :
http://github.com/jmettraux/ruote/commit/ec702048a1ac840dea8e1c1810ac0cfdfb75dcc9
> 2. Looking at the ruote-rest (using ruote 1.x) implementation, there
> seems to be the ability to pause various parts of the engine
> (participants and the engine itself). However, we couldn't find this
> functionality in ruote 2.0. Was this left out on purpose or should we
> expect it in the future?
Still thinking about how to implement it right in ruote 2.0
(especially with respect to timeouts). Engine pause is easier to
implement that process pause.
Out in the wild, process pause is usually synonymous with "the human
participant still hasn't replied".
Maybe you have a strong use case for it, please tell us about it.
> 3. Most importantly, I noticed the behavior of the
> concurrent_iterator has changed (and is possibly broken). In ruote
> 1.x concurrent iterator spawns x instances of its block. Each
> instance must reply before the loop replies. However, in ruote 2.0 it
> seems the loop exists when only one of many instances receives a
> reply. Here's a simple process definition that should illustrate the
> differences:
>
> process_definition do
> sequence do
> concurrent_iterator :on_value => (1..10).to_a, :to_field => "f" do
> cursor :rewind_if => '${f:__timed_out__}' do
> # Delete the timed out field in case it was set from a
> previous loop
> unset :field => "__timed_out__"
> participant_0
> participant_1 :timeout => "1m"
> end
> end
> participant_2
> end
> end
>
> All the participants of this definition are FsParticipants.
Do you have a simpler case with detailed explanation ?
The concurrent_iterator behaves as specified :
The cursor behaves as specified :
Maybe you could write a similar test case that exhibits the flaw you
mention. Please trim it to the essential.
> 4. You'll notice in the example above I unset the __timed_out_ field
> as it's left over from the previous run and will cause available_task
> to reply immediately. Should this be the default behavior or should
> participants clear this value upon initialization? I'm on the fence
> about this one as the field may be useful to a later participant.
I'm sitting on the same fence as you. I was thinking of maybe storing
the timeout information in an array instead of the current "timeout
information overrides any previous timeout information".
Also note that ruote 2.0 introduces an "on_timeout" (Thanks @hassox
and @kennethkalmer) attribute which you can use to write
jason :timeout => '2d', :on_timeout => 'asm'
where after two days, the workitem is handed to asm. You can specify a
participant name or a subprocess name, or the word 'error' to trigger
an error.
Hope this will help, best regards,
Hello,
OK, I added a TODO note for it.
> Here is a much simpler Ruote 2.0 example that demonstrates the
> concurrent_iterator problem I'm having:
>
> ::Ruote.process_definition :name => "concurrent_iterator" do
> sequence do
> concurrent_iterator :on_value => (1..10).to_a, :to_field => "f" do
> sequence do
> participant_1
> participant_2
> end
> end
> participant_3
> end
> end
>
> This definition will exit the iterator loop (and reach participant_3)
> as soon as only one of the concurrent sequences contained within
> replies. It seems the only difference between this example and those
> in the tests is I've nested a sequence inside of the loop instead of
> just a bare participant.
I have added a test replicating yours :
http://github.com/jmettraux/ruote/commit/2f120a4b5efb7d802b1d6dd55bbb71c6a7e3c67a
(had to fix two things in fs_participant to make it work as I wanted to)
> An array of timeout history is not a bad idea but could lead to memory
> problems as tasks continue to loop. For the moment, I'm ok with
> unsetting the field or using the syntax you mentioned below.
OK, will think about it, thanks for the input.
Cheers,