ruote 2.1.10 → 2.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.txt +51 -1
- data/CREDITS.txt +9 -0
- data/README.rdoc +13 -0
- data/Rakefile +50 -21
- data/TODO.txt +42 -4
- data/examples/pong.rb +37 -0
- data/lib/ruote/context.rb +19 -9
- data/lib/ruote/engine/process_error.rb +10 -0
- data/lib/ruote/engine/process_status.rb +140 -41
- data/lib/ruote/engine.rb +394 -27
- data/lib/ruote/exp/command.rb +2 -0
- data/lib/ruote/exp/fe_concurrence.rb +8 -0
- data/lib/ruote/exp/fe_concurrent_iterator.rb +3 -0
- data/lib/ruote/exp/fe_cursor.rb +48 -4
- data/lib/ruote/exp/fe_iterator.rb +40 -0
- data/lib/ruote/exp/fe_listen.rb +3 -3
- data/lib/ruote/exp/fe_participant.rb +30 -12
- data/lib/ruote/exp/fe_ref.rb +126 -0
- data/lib/ruote/exp/fe_subprocess.rb +20 -1
- data/lib/ruote/exp/fe_wait.rb +4 -1
- data/lib/ruote/exp/fe_when.rb +7 -10
- data/lib/ruote/exp/flowexpression.rb +23 -12
- data/lib/ruote/exp/ro_attributes.rb +5 -8
- data/lib/ruote/exp/ro_variables.rb +4 -2
- data/lib/ruote/fei.rb +2 -0
- data/lib/ruote/id/wfid_generator.rb +1 -1
- data/lib/ruote/log/pretty.rb +137 -0
- data/lib/ruote/log/storage_history.rb +1 -1
- data/lib/ruote/log/test_logger.rb +51 -126
- data/lib/ruote/log/wait_logger.rb +8 -13
- data/lib/ruote/parser/ruby_dsl.rb +4 -4
- data/lib/ruote/parser.rb +2 -2
- data/lib/ruote/part/block_participant.rb +1 -1
- data/lib/ruote/part/engine_participant.rb +1 -1
- data/lib/ruote/part/storage_participant.rb +27 -28
- data/lib/ruote/part/template.rb +8 -3
- data/lib/ruote/receiver/base.rb +24 -6
- data/lib/ruote/storage/base.rb +76 -11
- data/lib/ruote/storage/fs_storage.rb +10 -0
- data/lib/ruote/storage/hash_storage.rb +19 -8
- data/lib/ruote/{part → svc}/dispatch_pool.rb +3 -2
- data/lib/ruote/svc/dollar_sub.rb +265 -0
- data/lib/ruote/{error_handler.rb → svc/error_handler.rb} +6 -1
- data/lib/ruote/{exp → svc}/expression_map.rb +31 -37
- data/lib/ruote/{part → svc}/participant_list.rb +165 -25
- data/lib/ruote/{evt → svc}/tracker.rb +0 -0
- data/lib/ruote/{util → svc}/treechecker.rb +0 -0
- data/lib/ruote/util/look.rb +4 -1
- data/lib/ruote/util/ometa.rb +21 -5
- data/lib/ruote/{subprocess.rb → util/subprocess.rb} +0 -0
- data/lib/ruote/version.rb +1 -1
- data/lib/ruote/worker.rb +29 -69
- data/lib/ruote/workitem.rb +28 -1
- data/ruote.gemspec +26 -22
- data/test/functional/base.rb +3 -0
- data/test/functional/concurrent_base.rb +1 -0
- data/test/functional/crunner.sh +1 -1
- data/test/functional/ct_0_concurrence.rb +6 -0
- data/test/functional/ct_1_iterator.rb +3 -0
- data/test/functional/ct_2_cancel.rb +5 -0
- data/test/functional/eft_13_iterator.rb +39 -4
- data/test/functional/eft_14_cursor.rb +39 -0
- data/test/functional/eft_30_ref.rb +140 -0
- data/test/functional/eft_3_participant.rb +25 -23
- data/test/functional/ft_10_dollar.rb +17 -1
- data/test/functional/ft_14_re_apply.rb +76 -0
- data/test/functional/ft_1_process_status.rb +170 -29
- data/test/functional/ft_20_storage_participant.rb +14 -0
- data/test/functional/ft_24_block_participants.rb +1 -1
- data/test/functional/ft_26_participant_timeout.rb +93 -0
- data/test/functional/ft_2_errors.rb +24 -17
- data/test/functional/ft_30_smtp_participant.rb +7 -2
- data/test/functional/ft_38_participant_more.rb +15 -0
- data/test/functional/ft_39_wait_for.rb +34 -1
- data/test/functional/ft_3_participant_registration.rb +270 -2
- data/test/functional/ft_40_wait_logger.rb +61 -0
- data/test/functional/ft_42_storage_copy.rb +4 -0
- data/test/functional/{ft_40_participant_on_reply.rb → ft_43_participant_on_reply.rb} +17 -0
- data/test/functional/ft_44_var_participant.rb +35 -0
- data/test/functional/ft_45_participant_accept.rb +64 -0
- data/test/functional/ft_46_launch_single.rb +49 -0
- data/test/functional/ft_5_on_error.rb +39 -1
- data/test/functional/storage_helper.rb +7 -1
- data/test/test_helper.rb +1 -1
- data/test/unit/storage.rb +105 -32
- data/test/unit/ut_0_ruby_parser.rb +31 -1
- data/test/unit/ut_16_parser.rb +20 -0
- data/test/unit/ut_19_part_template.rb +11 -1
- data/test/unit/ut_20_composite_storage.rb +1 -1
- data/test/unit/ut_4_expmap.rb +1 -1
- data/test/unit/ut_6_condition.rb +2 -2
- metadata +112 -74
- data/lib/ruote/exp/raw.rb +0 -44
- data/lib/ruote/util/dollar.rb +0 -193
data/CHANGELOG.txt
CHANGED
@@ -2,6 +2,56 @@
|
|
2
2
|
= ruote - CHANGELOG.txt
|
3
3
|
|
4
4
|
|
5
|
+
== ruote - 2.1.11 released 2010/10/01
|
6
|
+
|
7
|
+
- Engine#process broken with process where schedule count > 1 (Thanks David)
|
8
|
+
- Engine#launch_single for 1! instance processes (Thanks Eric)
|
9
|
+
- Workitem#command and #command= helpers
|
10
|
+
- ProcessError#workitem helper
|
11
|
+
- fetch_flow_expression made public and aliased to fexp
|
12
|
+
- ${r:workitem_field} (idea: Nathan Stults)
|
13
|
+
- Ruote::Dollar::Dict and Ruote::Dollar::RubyContext
|
14
|
+
- made Ruote.dsub a service : @context.dollar_sub.s(...) (idea: Nathan Stults)
|
15
|
+
- moved simpler services to ruote/svc/
|
16
|
+
- using BlankSlate for ruby process definitions
|
17
|
+
- Engine.new(worker, :join => true) will let the worker run in the current
|
18
|
+
thread (and not return)
|
19
|
+
- StorageParticipant#query(:count => true)
|
20
|
+
- storage.get_many(type, keys, :descending => true)
|
21
|
+
- engine.processes(:skip => 50, limit => 50)
|
22
|
+
- listen expression : using lwfid instead of wfid (storage change)
|
23
|
+
- fixed issue when re-applying root expressions (Thanks Brett)
|
24
|
+
- storage_participant.query using :skip and :limit
|
25
|
+
- engine.schedules([wfid]) and ProcessStatus#schedules
|
26
|
+
- differentiating on_re_apply from on_cancel (process gardening)
|
27
|
+
- engine.participant_list= more tolerant about its input
|
28
|
+
- engine.process(wfid).stored_workitems
|
29
|
+
- engine.process(wfid).workitems and .position
|
30
|
+
- engine.process(wfid).last_active
|
31
|
+
- engine.errors(wfid=nil) now returns array of ProcessError instances
|
32
|
+
- engine.register { block } (Torsten)
|
33
|
+
- participant.accept?(workitem)
|
34
|
+
- 'ref' expression (pointing to participants or subprocesses)
|
35
|
+
- engine.process_wfids (list process instance wfids)
|
36
|
+
- set 'v:alpha' => [ 'MyParticipant', { 'flavour' => 'vanilla' }]
|
37
|
+
participants registered as variables (just for that process instance)
|
38
|
+
- engine.participant_list and .participant_list=
|
39
|
+
- engine.register_participant 'al', 'AlParticipant', :require_path => 'pa/th'
|
40
|
+
- engine.register_participant 'al', 'AlParticipant', :load_path => 'pa/th'
|
41
|
+
- engine.[un]register for .[un]register_participant
|
42
|
+
- engine.noisy = true (a shortcut)
|
43
|
+
- engine.storage_participant (a shortcut)
|
44
|
+
- removed direct dependency on rufus-lru
|
45
|
+
- WaitLogger : a transient @seen (Thanks Kaspar)
|
46
|
+
- error_handler : more error catching
|
47
|
+
- storage#copy_to(other_storage) item by item implementation
|
48
|
+
- Engine#wait_for OK with multiple threads
|
49
|
+
- ExpressionMap now loads all expressions in Ruote::Exp:: namespace
|
50
|
+
- 'error_intercepted' msg now features error_class, _message and _backtrace (RM)
|
51
|
+
- Engine#join and Worker#join
|
52
|
+
- workitem.error now includes error's backtrace (contributed by Rich Meyers)
|
53
|
+
|
54
|
+
|
5
55
|
== ruote - 2.1.10 released 2010/06/15
|
6
56
|
|
7
57
|
- storage#copy_to(other_storage) implemented
|
@@ -30,7 +80,7 @@
|
|
30
80
|
- Workitem#error and Workitem#timed_out shortcuts
|
31
81
|
- participant :on_error => 'x' broken. Fixed. Thanks Oleg.
|
32
82
|
- Engine#workitem(fei) for advanced users
|
33
|
-
-
|
83
|
+
- LocalParticipant : added a reject(workitem) method
|
34
84
|
- participant exp : dispatched = true set right after dispatch
|
35
85
|
|
36
86
|
|
data/CREDITS.txt
CHANGED
@@ -16,6 +16,10 @@ Torsten Schoenebaum - http://github.com/tosch
|
|
16
16
|
Contributors
|
17
17
|
------------
|
18
18
|
|
19
|
+
David Goodlad - http://github.com/dgoodlad
|
20
|
+
Eric Dennis - http://github.com/threetee
|
21
|
+
David Greaves - http://github.com/lbt
|
22
|
+
Rich Meyers - http://github.com/richmeyers
|
19
23
|
Oleg Pudeyev - http://github.com/p
|
20
24
|
Brett Anthoine - http://github.com/anb
|
21
25
|
Matt Nichols - http://github.com/mattnichols
|
@@ -39,6 +43,11 @@ Richard Jennings
|
|
39
43
|
Feedback
|
40
44
|
--------
|
41
45
|
|
46
|
+
Eric Platon - engine.launch_single idea
|
47
|
+
Marc Lee - storage.clear consistency
|
48
|
+
Nathan Stults - enhanced dollar substitution and service
|
49
|
+
Don H. French - Engine#register_from_dir idea
|
50
|
+
Kaspar Schiess - http://github.com/kschiess
|
42
51
|
Oleg (foenixx) - many suggestions and bug reports
|
43
52
|
Avishai Shalom - discussion and ideas about participant/worker locality
|
44
53
|
Gonzalo Suarez - many help
|
data/README.rdoc
CHANGED
@@ -12,6 +12,19 @@ Process definitions are mainly describing how workitems are routed to participan
|
|
12
12
|
|
13
13
|
== usage
|
14
14
|
|
15
|
+
grab ruote
|
16
|
+
|
17
|
+
gem install ruote
|
18
|
+
gem install yajl-ruby
|
19
|
+
|
20
|
+
Note : the json gem has a serious bug :
|
21
|
+
|
22
|
+
http://github.com/flori/json/issues#issue/21
|
23
|
+
|
24
|
+
So yajl-ruby is seriously recommended.
|
25
|
+
|
26
|
+
Then
|
27
|
+
|
15
28
|
require 'rubygems'
|
16
29
|
require 'ruote'
|
17
30
|
require 'ruote/storage/fs_storage'
|
data/Rakefile
CHANGED
@@ -4,6 +4,17 @@ require 'lib/ruote/version.rb'
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'rake'
|
6
6
|
|
7
|
+
#
|
8
|
+
# clean
|
9
|
+
|
10
|
+
require 'rake/clean'
|
11
|
+
CLEAN.include('pkg', 'rdoc', 'ruote_work', 'ruote_data', 'logs')
|
12
|
+
|
13
|
+
task :default => [ :clean ]
|
14
|
+
|
15
|
+
|
16
|
+
#
|
17
|
+
# jeweler tasks
|
7
18
|
|
8
19
|
begin
|
9
20
|
|
@@ -23,10 +34,9 @@ ruote is an open source ruby workflow engine.
|
|
23
34
|
gem.rubyforge_project = 'ruote'
|
24
35
|
gem.test_file = 'test/test.rb'
|
25
36
|
|
26
|
-
gem.add_dependency 'rufus-json', '>= 0.2.
|
27
|
-
gem.add_dependency 'rufus-cloche', '>= 0.1.
|
37
|
+
gem.add_dependency 'rufus-json', '>= 0.2.5'
|
38
|
+
gem.add_dependency 'rufus-cloche', '>= 0.1.20'
|
28
39
|
gem.add_dependency 'rufus-dollar'
|
29
|
-
gem.add_dependency 'rufus-lru'
|
30
40
|
gem.add_dependency 'rufus-mnemo', '>= 1.1.0'
|
31
41
|
gem.add_dependency 'rufus-scheduler', '>= 2.0.5'
|
32
42
|
gem.add_dependency 'rufus-treechecker', '>= 1.0.3'
|
@@ -41,32 +51,51 @@ ruote is an open source ruby workflow engine.
|
|
41
51
|
# Gem::Specification http://www.rubygems.org/read/chapter/20
|
42
52
|
end
|
43
53
|
Jeweler::GemcutterTasks.new
|
54
|
+
|
44
55
|
rescue LoadError
|
45
56
|
puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
|
46
57
|
end
|
47
58
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# rdoc
|
62
|
+
|
63
|
+
#begin
|
64
|
+
# require 'yard'
|
65
|
+
# YARD::Rake::YardocTask.new do |doc|
|
66
|
+
# doc.options = [ '-o', 'rdoc', '--title', "ruote #{Ruote::VERSION}" ]
|
67
|
+
# end
|
68
|
+
#rescue LoadError
|
69
|
+
# task :yard do
|
70
|
+
# abort 'YARD is not available. In order to run yardoc, you must: sudo gem install yard'
|
71
|
+
# end
|
72
|
+
#end
|
73
|
+
|
74
|
+
#
|
75
|
+
# make sure to have rdoc 2.5.x to run that
|
76
|
+
#
|
77
|
+
require 'rake/rdoctask'
|
78
|
+
Rake::RDocTask.new do |rd|
|
79
|
+
|
80
|
+
rd.main = 'README.rdoc'
|
81
|
+
rd.rdoc_dir = 'rdoc'
|
82
|
+
|
83
|
+
rd.rdoc_files.include(
|
84
|
+
'README.rdoc', 'CHANGELOG.txt', 'CREDITS.txt', 'lib/**/*.rb')
|
85
|
+
|
86
|
+
rd.title = "ruote #{Ruote::VERSION}"
|
57
87
|
end
|
58
88
|
|
59
|
-
require 'rake/clean'
|
60
|
-
CLEAN.include('pkg', 'rdoc', 'work', 'logs')
|
61
89
|
|
62
|
-
|
90
|
+
#
|
91
|
+
# upload_rdoc
|
63
92
|
|
64
93
|
desc 'Upload the documentation to rubyforge'
|
65
|
-
task :upload_rdoc => :
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
}
|
94
|
+
task :upload_rdoc => [ :clean, :rdoc ] do
|
95
|
+
|
96
|
+
account = 'jmettraux@rubyforge.org'
|
97
|
+
webdir = '/var/www/gforge-projects/ruote'
|
98
|
+
|
99
|
+
sh "rsync -azv -e ssh rdoc #{account}:#{webdir}/"
|
71
100
|
end
|
72
101
|
|
data/TODO.txt
CHANGED
@@ -214,6 +214,26 @@
|
|
214
214
|
[o] storage participant : accept string for fei
|
215
215
|
[o] => Ruote::FlowExpressionId.extract(x)
|
216
216
|
[o] fei : place engine id in fei.to_storage_id (and back)
|
217
|
+
[o] wait_for(:inactive) blocks until worker is inactive
|
218
|
+
[o] storage0.copy_to(storage1) / migrate_to as requested by Matt Nichols
|
219
|
+
[o] check if rufus-lru is still needed
|
220
|
+
[o] storage migration : eats all the memory :(
|
221
|
+
[x] remove dependency on rufus-scheduler
|
222
|
+
[o] engine.storage_participant
|
223
|
+
[o] engine.noisy = true shortcut
|
224
|
+
[o] (ft_27) set "v:mypart" => [ 'MyParticipant', {} ]
|
225
|
+
binding a participant on the fly (just for this process)
|
226
|
+
[o] participant timeout as an instance method
|
227
|
+
[o] engine.process_wfids (lighter than engine.processes)
|
228
|
+
[o] storage.get_many(x, y, :descending => true) ?
|
229
|
+
[o] storage_participant.query : use skip and limit
|
230
|
+
[o] engine.processes use skip and limit
|
231
|
+
[o] engine.errors use skip and limit
|
232
|
+
[o] ParticipantEntry is a bit brittle when editing engine.participant_list
|
233
|
+
[o] use blank slate for process definition
|
234
|
+
[o] lib/ruote/svc for treechecker, error_handler and co (tree_checker)
|
235
|
+
[o] part/template.rb, use Rufus::Json.pretty_encode
|
236
|
+
[o] storage.clear OR storage.purge! OR both (cf discussion with marc_lee) !!
|
217
237
|
|
218
238
|
[ ] exp : exp (restricted form of eval ?)
|
219
239
|
[ ] exp : case (is it necessary ?)
|
@@ -358,12 +378,30 @@
|
|
358
378
|
|
359
379
|
[ ] solve the ps#root_expression_for(fei) dilemma
|
360
380
|
|
361
|
-
[ ] engine.noisy = true shortcut
|
362
|
-
|
363
381
|
[ ] re_apply_stalled
|
364
382
|
http://groups.google.com/group/openwferu-users/browse_thread/thread/ff29f26d6b5fd135
|
365
383
|
|
366
|
-
[ ]
|
384
|
+
[ ] engine.purge (arts style : worker.@msgs = [])
|
385
|
+
|
386
|
+
[ ] http://ruote.rubyforge.org/irclogs/ruote_2010-07-07.txt
|
387
|
+
configuration issue
|
388
|
+
maybe fail with a good error message when registering service...
|
389
|
+
|
390
|
+
[ ] participant 'toto', :while => '${not_good}' (really ?)
|
391
|
+
|
392
|
+
[ ] engine.register_from_dir() have a way to re-evaluate the dir
|
393
|
+
[o] OR remove engine.register_from_dir()
|
394
|
+
[o] AND provide a better register &block
|
395
|
+
[o] provide a mean for a participant to reject a workitem (intra plist)
|
396
|
+
on_reply and now filter ?
|
397
|
+
|
398
|
+
[ ] rw : upgrade [register_]participant documentation
|
399
|
+
|
400
|
+
[ ] StorageParticipant#by_store[_name]
|
401
|
+
maybe : reform the store_name system !
|
402
|
+
|
403
|
+
[ ] rename 'parser' to 'reader'
|
367
404
|
|
368
|
-
[ ]
|
405
|
+
[ ] process_count and error_count ? (processes(:count => true))
|
406
|
+
[ ] engine.ps(wfid) (shortcut ?)
|
369
407
|
|
data/examples/pong.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
# http://gist.github.com/596822
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'ruote'
|
6
|
+
|
7
|
+
pdef = Ruote.process_definition do
|
8
|
+
repeat do
|
9
|
+
ping # mister ping, please shoot first
|
10
|
+
pong
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Opponent
|
15
|
+
include Ruote::LocalParticipant
|
16
|
+
|
17
|
+
def initialize (options)
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def consume (workitem)
|
22
|
+
puts @options['sound']
|
23
|
+
reply_to_engine(workitem)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
engine = Ruote::Engine.new(Ruote::Worker.new(Ruote::HashStorage.new))
|
28
|
+
|
29
|
+
engine.register_participant :ping, Opponent, 'sound' => 'ping'
|
30
|
+
engine.register_participant :pong, Opponent, 'sound' => 'pong'
|
31
|
+
|
32
|
+
wfid = engine.launch(pdef)
|
33
|
+
|
34
|
+
sleep 5 # five seconds of ping pong fun
|
35
|
+
|
36
|
+
engine.cancel_process(wfid) # game over
|
37
|
+
|
data/lib/ruote/context.rb
CHANGED
@@ -113,7 +113,7 @@ module Ruote
|
|
113
113
|
|
114
114
|
service = if klass
|
115
115
|
|
116
|
-
require(path)
|
116
|
+
require(path) if path
|
117
117
|
|
118
118
|
aa = [ self ]
|
119
119
|
aa << opts if opts
|
@@ -125,6 +125,14 @@ module Ruote
|
|
125
125
|
end
|
126
126
|
|
127
127
|
self.class.class_eval %{ def #{key[2..-1]}; @services['#{key}']; end }
|
128
|
+
#
|
129
|
+
# This 'one-liner' will add an instance method to Context for this
|
130
|
+
# service.
|
131
|
+
#
|
132
|
+
# If the service key is 's_dishwasher', then the service will be
|
133
|
+
# available via Context#dishwasher.
|
134
|
+
#
|
135
|
+
# I.e. dishwasher = engine.context.dishwasher
|
128
136
|
|
129
137
|
service
|
130
138
|
end
|
@@ -163,19 +171,21 @@ module Ruote
|
|
163
171
|
's_parser' => [
|
164
172
|
'ruote/parser', 'Ruote::Parser' ],
|
165
173
|
's_treechecker' => [
|
166
|
-
'ruote/
|
174
|
+
'ruote/svc/treechecker', 'Ruote::TreeChecker' ],
|
167
175
|
's_expmap' => [
|
168
|
-
'ruote/
|
176
|
+
'ruote/svc/expression_map', 'Ruote::ExpressionMap' ],
|
169
177
|
's_tracker' => [
|
170
|
-
'ruote/
|
178
|
+
'ruote/svc/tracker', 'Ruote::Tracker' ],
|
171
179
|
's_plist' => [
|
172
|
-
'ruote/
|
180
|
+
'ruote/svc/participant_list', 'Ruote::ParticipantList' ],
|
173
181
|
's_dispatch_pool' => [
|
174
|
-
'ruote/
|
175
|
-
'
|
176
|
-
'ruote/
|
182
|
+
'ruote/svc/dispatch_pool', 'Ruote::DispatchPool' ],
|
183
|
+
's_dollar_sub' => [
|
184
|
+
'ruote/svc/dollar_sub', 'Ruote::DollarSubstitution' ],
|
177
185
|
's_error_handler' => [
|
178
|
-
'ruote/error_handler', 'Ruote::ErrorHandler' ]
|
186
|
+
'ruote/svc/error_handler', 'Ruote::ErrorHandler' ],
|
187
|
+
's_logger' => [
|
188
|
+
'ruote/log/wait_logger', 'Ruote::WaitLogger' ] }
|
179
189
|
end
|
180
190
|
end
|
181
191
|
end
|
@@ -50,6 +50,10 @@ module Ruote
|
|
50
50
|
Ruote::FlowExpressionId.new(msg['fei'])
|
51
51
|
end
|
52
52
|
|
53
|
+
def wfid
|
54
|
+
msg['fei']['wfid']
|
55
|
+
end
|
56
|
+
|
53
57
|
def tree
|
54
58
|
@h['msg']['tree']
|
55
59
|
end
|
@@ -82,6 +86,12 @@ module Ruote
|
|
82
86
|
@h['msg']['workitem']['fields']
|
83
87
|
end
|
84
88
|
|
89
|
+
# Returns an instance of Ruote::Workitem
|
90
|
+
#
|
91
|
+
def workitem
|
92
|
+
Ruote::Workitem.new(msg['workitem'])
|
93
|
+
end
|
94
|
+
|
85
95
|
protected
|
86
96
|
|
87
97
|
def to_dot (opts)
|
@@ -38,20 +38,35 @@ module Ruote
|
|
38
38
|
#
|
39
39
|
attr_reader :expressions
|
40
40
|
|
41
|
+
# An array of the workitems currently in the storage participant for this
|
42
|
+
# process instance.
|
43
|
+
#
|
44
|
+
# Do not confuse with #workitems
|
45
|
+
#
|
46
|
+
attr_reader :stored_workitems
|
47
|
+
|
41
48
|
# An array of errors currently plaguing the process instance. Hopefully,
|
42
49
|
# this array is empty.
|
43
50
|
#
|
44
51
|
attr_reader :errors
|
45
52
|
|
46
|
-
|
53
|
+
# An array of schedules (open structs yielding information about the
|
54
|
+
# schedules of this process)
|
55
|
+
#
|
56
|
+
attr_reader :schedules
|
57
|
+
|
58
|
+
def initialize (context, expressions, stored_workitems, errors, schedules)
|
47
59
|
|
48
60
|
@expressions = expressions.collect { |e|
|
49
61
|
Ruote::Exp::FlowExpression.from_h(context, e) }
|
50
62
|
@expressions.sort! { |a, b| a.fei.expid <=> b.fei.expid }
|
51
63
|
|
52
|
-
@
|
53
|
-
|
54
|
-
|
64
|
+
@stored_workitems = stored_workitems.collect { |h|
|
65
|
+
Ruote::Workitem.new(h)
|
66
|
+
}
|
67
|
+
|
68
|
+
@errors = errors.sort! { |a, b| a.fei.expid <=> b.fei.expid }
|
69
|
+
@schedules = schedules.sort! { |a, b| a['owner'].sid <=> b['owner'].sid }
|
55
70
|
end
|
56
71
|
|
57
72
|
# Returns the expression at the root of the process instance.
|
@@ -134,23 +149,97 @@ module Ruote
|
|
134
149
|
#
|
135
150
|
def wfid
|
136
151
|
|
137
|
-
|
138
|
-
root_expression.fei.wfid
|
139
|
-
rescue
|
140
|
-
@errors.first.fei.wfid
|
141
|
-
end
|
152
|
+
@expressions.any? ? @expressions.first.fei.wfid : @errors.first.fei.wfid
|
142
153
|
end
|
143
154
|
|
155
|
+
# For a process
|
156
|
+
#
|
157
|
+
# Ruote.process_definition :name => 'review', :revision => '0.1' do
|
158
|
+
# author
|
159
|
+
# reviewer
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# will yield 'review'.
|
163
|
+
#
|
144
164
|
def definition_name
|
145
165
|
|
146
166
|
root_expression.attribute('name') || root_expression.attribute_text
|
147
167
|
end
|
148
168
|
|
169
|
+
# For a process
|
170
|
+
#
|
171
|
+
# Ruote.process_definition :name => 'review', :revision => '0.1' do
|
172
|
+
# author
|
173
|
+
# reviewer
|
174
|
+
# end
|
175
|
+
#
|
176
|
+
# will yield '0.1'.
|
177
|
+
#
|
149
178
|
def definition_revision
|
150
179
|
|
151
180
|
root_expression.attribute('revision')
|
152
181
|
end
|
153
182
|
|
183
|
+
# Returns the 'position' of the process.
|
184
|
+
#
|
185
|
+
# pdef = Ruote.process_definition do
|
186
|
+
# alpha :task => 'clean car'
|
187
|
+
# end
|
188
|
+
# wfid = engine.launch(pdef)
|
189
|
+
#
|
190
|
+
# sleep 0.500
|
191
|
+
#
|
192
|
+
# engine.process(wfid) # => [["0_0", "alpha", {"task"=>"clean car"}]]
|
193
|
+
#
|
194
|
+
# A process with concurrent branches will yield multiple 'positions'.
|
195
|
+
#
|
196
|
+
# It uses #workitems underneath.
|
197
|
+
#
|
198
|
+
def position
|
199
|
+
|
200
|
+
workitems.collect { |wi|
|
201
|
+
r = [ wi.fei.sid, wi.participant_name ]
|
202
|
+
params = wi.fields['params'].dup
|
203
|
+
params.delete('ref')
|
204
|
+
r << params
|
205
|
+
r
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
# Returns a list of the workitems currently 'out' to participants
|
210
|
+
#
|
211
|
+
# For example, with an instance of
|
212
|
+
#
|
213
|
+
# Ruote.process_definition do
|
214
|
+
# concurrence do
|
215
|
+
# alpha :task => 'clean car'
|
216
|
+
# bravo :task => 'sell car'
|
217
|
+
# end
|
218
|
+
# end
|
219
|
+
#
|
220
|
+
# calling engine.process(wfid).workitems will yield two workitems
|
221
|
+
# (alpha and bravo).
|
222
|
+
#
|
223
|
+
# Warning : do not confuse the workitems here with the workitems held
|
224
|
+
# in a storage participant or equivalent.
|
225
|
+
#
|
226
|
+
def workitems
|
227
|
+
|
228
|
+
@expressions.select { |fexp|
|
229
|
+
fexp.is_a?(Ruote::Exp::ParticipantExpression)
|
230
|
+
}.collect { |fexp|
|
231
|
+
Ruote::Workitem.new(fexp.h.applied_workitem)
|
232
|
+
}
|
233
|
+
end
|
234
|
+
|
235
|
+
# Returns a parseable UTC datetime string which indicates when the process
|
236
|
+
# was last active.
|
237
|
+
#
|
238
|
+
def last_active
|
239
|
+
|
240
|
+
@expressions.collect { |fexp| fexp.h.put_at }.max
|
241
|
+
end
|
242
|
+
|
154
243
|
# Returns the process definition tree as it was when this process instance
|
155
244
|
# was launched.
|
156
245
|
#
|
@@ -170,25 +259,33 @@ module Ruote
|
|
170
259
|
|
171
260
|
"(process_status wfid '#{wfid}', " +
|
172
261
|
"expressions #{@expressions.size}, " +
|
173
|
-
"
|
262
|
+
"stored_workitems #{@stored_workitems.size}, " +
|
263
|
+
"errors #{@errors.size}, " +
|
264
|
+
"schedules #{@schedules.size}, " +
|
265
|
+
")"
|
174
266
|
end
|
175
267
|
|
176
268
|
def inspect
|
177
269
|
|
178
|
-
s = "== #{self.class}
|
179
|
-
s << " expressions : #{@expressions.size}
|
270
|
+
s = [ "== #{self.class} ==" ]
|
271
|
+
s << " expressions : #{@expressions.size}"
|
180
272
|
@expressions.each do |e|
|
181
|
-
s << " #{e.fei.to_storage_id} : #{e}
|
273
|
+
s << " #{e.fei.to_storage_id} : #{e}"
|
182
274
|
end
|
183
|
-
s << " errors : #{@errors.size}
|
275
|
+
s << " errors : #{@errors.size}"
|
184
276
|
@errors.each do |e|
|
185
|
-
s << " #{e.fei.to_storage_id}
|
186
|
-
s << " #{e.inspect}
|
277
|
+
s << " #{e.fei.to_storage_id} :" if e.fei
|
278
|
+
s << " #{e.inspect}"
|
187
279
|
end
|
280
|
+
s << " schedules : #{@schedules.size}"
|
281
|
+
s << " stored workitems : #{@stored_workitems.size}"
|
188
282
|
|
189
|
-
s
|
283
|
+
s.join("\n") + "\n"
|
190
284
|
end
|
191
285
|
|
286
|
+
# Returns a 'dot' representation of the process. A graph describing
|
287
|
+
# the tree of flow expressions that compose the process.
|
288
|
+
#
|
192
289
|
def to_dot (opts={})
|
193
290
|
|
194
291
|
s = [ "digraph \"process wfid #{wfid}\" {" ]
|
@@ -199,27 +296,24 @@ module Ruote
|
|
199
296
|
s.join("\n")
|
200
297
|
end
|
201
298
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
h
|
222
|
-
end
|
299
|
+
#--
|
300
|
+
#def to_h
|
301
|
+
# h = {}
|
302
|
+
# %w[
|
303
|
+
# wfid
|
304
|
+
# definition_name definition_revision
|
305
|
+
# original_tree current_tree
|
306
|
+
# variables tags
|
307
|
+
# ].each { |m| h[m] = self.send(m) }
|
308
|
+
# h['launched_time'] = launched_time
|
309
|
+
# h['last_active'] = last_active
|
310
|
+
# # all_variables and all_tags ?
|
311
|
+
# h['root_expression'] = nil
|
312
|
+
# h['expressions'] = @expressions.collect { |e| e.fei.to_h }
|
313
|
+
# h['errors'] = @errors.collect { |e| e.to_h }
|
314
|
+
# h
|
315
|
+
#end
|
316
|
+
#++
|
223
317
|
|
224
318
|
# Returns the current version of the process definition tree. If no
|
225
319
|
# manipulation (gardening) was performed on the tree, this method yields
|
@@ -230,15 +324,21 @@ module Ruote
|
|
230
324
|
h = Ruote.decompose_tree(original_tree)
|
231
325
|
|
232
326
|
@expressions.sort { |e0, e1|
|
327
|
+
|
233
328
|
e0.fei.expid <=> e1.fei.expid
|
329
|
+
|
234
330
|
}.each { |e|
|
235
|
-
|
331
|
+
|
332
|
+
trigger = e.tree[1]['_triggered']
|
333
|
+
|
334
|
+
tree = if trigger && trigger != 'on_re_apply'
|
236
335
|
t = original_tree_from_parent(e).dup
|
237
|
-
t[1]['_triggered'] =
|
336
|
+
t[1]['_triggered'] = trigger
|
238
337
|
t
|
239
338
|
else
|
240
339
|
e.tree
|
241
340
|
end
|
341
|
+
|
242
342
|
h.merge!(Ruote.decompose_tree(tree, e.fei.expid))
|
243
343
|
}
|
244
344
|
|
@@ -269,7 +369,6 @@ module Ruote
|
|
269
369
|
return nil unless t
|
270
370
|
|
271
371
|
t << []
|
272
|
-
|
273
372
|
i = 0
|
274
373
|
|
275
374
|
loop do
|