ruote 2.1.10 → 2.1.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|