ruote 2.1.4 → 2.1.5

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.
@@ -76,8 +76,9 @@ module Ruote
76
76
 
77
77
  def [] (key)
78
78
 
79
+ return @fexp.fei.to_storage_id if key == 'fei'
79
80
  return @fexp.fei.wfid if key == 'wfid'
80
- return @fexp.fei.parent_wfid if key == 'parent_wfid'
81
+ return @fexp.fei.sub_wfid if key == 'sub_wfid'
81
82
  return @fexp.fei.expid if key == 'expid'
82
83
 
83
84
  pr, k = extract_prefix(key)
@@ -149,10 +150,12 @@ module Ruote
149
150
  #
150
151
  def call_ruby (ruby_code)
151
152
 
152
- return '' if @fexp.context[:ruby_eval_allowed] != true
153
+ return '' if @fexp.context['ruby_eval_allowed'] != true
153
154
 
154
- wi = @workitem
155
- workitem = @workitem
155
+ engine_id = @fexp.context.engine_id
156
+
157
+ wi = Ruote::Workitem.new(@workitem)
158
+ workitem = wi
156
159
 
157
160
  fe = @fexp
158
161
  fexp = @fexp
@@ -168,7 +171,22 @@ module Ruote
168
171
 
169
172
  eval(ruby_code, binding()).to_s
170
173
  end
171
- end
172
174
 
175
+ # This 'd' function can be called from inside ${r:...} notations.
176
+ #
177
+ # pdef = Ruote.process_definition do
178
+ # sequence do
179
+ # set 'f:toto' => 'person'
180
+ # echo "${r:d('f:toto')}"
181
+ # end
182
+ # end
183
+ #
184
+ # will yield "person".
185
+ #
186
+ def d (s)
187
+
188
+ Rufus.dsub("${#{s}}", self)
189
+ end
190
+ end
173
191
  end
174
192
 
data/lib/ruote/worker.rb CHANGED
@@ -27,7 +27,7 @@ require 'ruote/fei'
27
27
 
28
28
  module Ruote
29
29
 
30
- VERSION = '2.1.4'
30
+ VERSION = '2.1.5'
31
31
 
32
32
  class Worker
33
33
 
@@ -137,6 +137,7 @@ module Ruote
137
137
  '_id' => "err_#{Ruote.to_storage_id(fei)}",
138
138
  'message' => ex.inspect,
139
139
  'trace' => ex.backtrace.join("\n"),
140
+ 'fei' => fei,
140
141
  'msg' => msg
141
142
  ) if fei
142
143
  end
@@ -154,7 +155,7 @@ module Ruote
154
155
 
155
156
  @last_time = now
156
157
 
157
- @storage.get_schedules(delta, now).each do|sche|
158
+ @storage.get_schedules(delta, now).each do |sche|
158
159
  trigger(sche)
159
160
  end
160
161
  end
@@ -283,8 +284,9 @@ module Ruote
283
284
 
284
285
  exp_hash = {
285
286
  'fei' => msg['fei'] || {
286
- 'engine_id' => @context['engine_id'] || 'engine',
287
+ 'engine_id' => @context.engine_id,
287
288
  'wfid' => msg['wfid'],
289
+ 'sub_wfid' => msg['sub_wfid'],
288
290
  'expid' => '0' },
289
291
  'parent_id' => msg['parent_id'],
290
292
  'original_tree' => tree,
@@ -303,6 +305,23 @@ module Ruote
303
305
  exp_class = Ruote::Exp::SequenceExpression
304
306
  end
305
307
 
308
+ if exp_class == Ruote::Exp::SubprocessExpression && tree[1]['engine']
309
+ #
310
+ # the subprocess has to be transformed into an EngineParticipant...
311
+
312
+ exp_class = Ruote::Exp::ParticipantExpression
313
+
314
+ atts = tree[1]
315
+
316
+ if ref = atts.find { |k, v| v.nil? }
317
+ ref = ref.first
318
+ atts.delete(ref)
319
+ end
320
+
321
+ atts['pdef'] = atts['ref'] || ref
322
+ atts['ref'] = atts.delete('engine')
323
+ end
324
+
306
325
  raise_unknown_expression_error(exp_hash) unless exp_class
307
326
 
308
327
  exp = exp_class.new(@context, exp_hash.merge!('original_tree' => tree))
@@ -313,7 +332,7 @@ module Ruote
313
332
  def raise_unknown_expression_error (exp_hash)
314
333
 
315
334
  exp_hash['state'] = 'failed'
316
- exp_hash['has_error'] = true
335
+ #exp_hash['has_error'] = true
317
336
 
318
337
  Ruote::Exp::RawExpression.new(@context, exp_hash).persist_or_raise
319
338
  # undigested expression is stored
@@ -340,12 +359,14 @@ module Ruote
340
359
  tree[1]['ref'] = key
341
360
  tree[1]['original_ref'] = tree[0] if key != tree[0]
342
361
 
343
- tree[0] = sub ? 'subprocess' : 'participant'
362
+ if sub
363
+
364
+ [ Ruote::Exp::SubprocessExpression, [ 'subprocess', *tree[1..2] ] ]
344
365
 
345
- [ sub ?
346
- Ruote::Exp::SubprocessExpression :
347
- Ruote::Exp::ParticipantExpression,
348
- tree ]
366
+ else
367
+
368
+ [ Ruote::Exp::ParticipantExpression, [ 'participant', *tree[1..2] ] ]
369
+ end
349
370
  else
350
371
 
351
372
  [ nil, tree ]
data/ruote.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruote}
8
- s.version = "2.1.4"
8
+ s.version = "2.1.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John Mettraux", "Kenneth Kalmer"]
12
- s.date = %q{2010-01-11}
12
+ s.date = %q{2010-01-28}
13
13
  s.description = %q{
14
14
  ruote is an open source ruby workflow engine.
15
15
  }
@@ -87,6 +87,7 @@ ruote is an open source ruby workflow engine.
87
87
  "lib/ruote/parser/xml.rb",
88
88
  "lib/ruote/part/block_participant.rb",
89
89
  "lib/ruote/part/dispatch_pool.rb",
90
+ "lib/ruote/part/engine_participant.rb",
90
91
  "lib/ruote/part/hash_participant.rb",
91
92
  "lib/ruote/part/local_participant.rb",
92
93
  "lib/ruote/part/no_op_participant.rb",
@@ -100,6 +101,7 @@ ruote is an open source ruby workflow engine.
100
101
  "lib/ruote/storage/base.rb",
101
102
  "lib/ruote/storage/fs_storage.rb",
102
103
  "lib/ruote/storage/hash_storage.rb",
104
+ "lib/ruote/subprocess.rb",
103
105
  "lib/ruote/tree_dot.rb",
104
106
  "lib/ruote/util/dollar.rb",
105
107
  "lib/ruote/util/hashdot.rb",
@@ -189,6 +191,7 @@ ruote is an open source ruby workflow engine.
189
191
  "test/functional/ft_34_cursor_rewind.rb",
190
192
  "test/functional/ft_35_add_service.rb",
191
193
  "test/functional/ft_36_storage_history.rb",
194
+ "test/functional/ft_37_engine_participant.rb",
192
195
  "test/functional/ft_3_participant_registration.rb",
193
196
  "test/functional/ft_4_cancel.rb",
194
197
  "test/functional/ft_5_on_error.rb",
@@ -93,7 +93,7 @@ class EftIncTest < Test::Unit::TestCase
93
93
 
94
94
  def test_inc_array
95
95
 
96
- @engine.context[:ruby_eval_allowed] = true
96
+ @engine.context['ruby_eval_allowed'] = true
97
97
 
98
98
  pdef = Ruote.process_definition do
99
99
  sequence do
@@ -113,7 +113,7 @@ class EftIncTest < Test::Unit::TestCase
113
113
 
114
114
  def test_inc_array_head
115
115
 
116
- @engine.context[:ruby_eval_allowed] = true
116
+ @engine.context['ruby_eval_allowed'] = true
117
117
 
118
118
  pdef = Ruote.process_definition do
119
119
  sequence do
@@ -133,7 +133,7 @@ class EftIncTest < Test::Unit::TestCase
133
133
 
134
134
  def test_inc_array_missing
135
135
 
136
- @engine.context[:ruby_eval_allowed] = true
136
+ @engine.context['ruby_eval_allowed'] = true
137
137
 
138
138
  pdef = Ruote.process_definition do
139
139
  sequence do
@@ -174,7 +174,7 @@ class EftIncTest < Test::Unit::TestCase
174
174
 
175
175
  def test_dec_array
176
176
 
177
- @engine.context[:ruby_eval_allowed] = true
177
+ @engine.context['ruby_eval_allowed'] = true
178
178
 
179
179
  pdef = Ruote.process_definition do
180
180
  sequence do
@@ -198,7 +198,7 @@ class EftIncTest < Test::Unit::TestCase
198
198
 
199
199
  def test_dec_to
200
200
 
201
- @engine.context[:ruby_eval_allowed] = true
201
+ @engine.context['ruby_eval_allowed'] = true
202
202
 
203
203
  pdef = Ruote.process_definition do
204
204
  sequence do
@@ -219,7 +219,7 @@ class EftIncTest < Test::Unit::TestCase
219
219
 
220
220
  def test_dec_val
221
221
 
222
- @engine.context[:ruby_eval_allowed] = true
222
+ @engine.context['ruby_eval_allowed'] = true
223
223
 
224
224
  pdef = Ruote.process_definition do
225
225
  sequence do
@@ -43,6 +43,25 @@ class FtDollarTest < Test::Unit::TestCase
43
43
  assert_trace(pdef, %w[ a b0 c0 d0 ])
44
44
  end
45
45
 
46
+ def test_nested_v
47
+
48
+ pdef = Ruote.process_definition do
49
+ sequence do
50
+ set(
51
+ :var => 'v0',
52
+ :val => {
53
+ 'name' => 'toto',
54
+ 'address' => [ 'e-street', 'atlantic_city' ] })
55
+ echo 'a:${v:v0.name}'
56
+ echo 'b:${v:v0.address.1}'
57
+ end
58
+ end
59
+
60
+ #noisy
61
+
62
+ assert_trace(pdef, %w[ a:toto b:atlantic_city ])
63
+ end
64
+
46
65
  def test_f
47
66
 
48
67
  pdef = Ruote.process_definition do
@@ -82,9 +101,73 @@ class FtDollarTest < Test::Unit::TestCase
82
101
 
83
102
  #noisy
84
103
 
85
- @engine.context[:ruby_eval_allowed] = true
104
+ @engine.context['ruby_eval_allowed'] = true
86
105
 
87
106
  assert_trace(pdef, '>3<')
88
107
  end
108
+
109
+ def test_r_and_wi
110
+
111
+ pdef = Ruote.process_definition do
112
+ sequence do
113
+ set 'f:toto' => 'person'
114
+ echo "${r:wi.fields['toto']}"
115
+ echo "${r:workitem.fields['toto']}"
116
+ end
117
+ end
118
+
119
+ #noisy
120
+
121
+ @engine.context['ruby_eval_allowed'] = true
122
+
123
+ assert_trace pdef, "person\nperson"
124
+ end
125
+
126
+ def test_r_and_d
127
+
128
+ pdef = Ruote.process_definition do
129
+ sequence do
130
+ set 'f:toto' => 'person'
131
+ echo "${r:d('f:toto')}"
132
+ end
133
+ end
134
+
135
+ #noisy
136
+
137
+ @engine.context['ruby_eval_allowed'] = true
138
+
139
+ assert_trace pdef, 'person'
140
+ end
141
+
142
+ def test_nested
143
+
144
+ pdef = Ruote.process_definition do
145
+ sequence do
146
+ set 'f:a' => 'a'
147
+ set 'v:a' => 'AA'
148
+ echo '${v:${f:a}}'
149
+ end
150
+ end
151
+
152
+ #noisy
153
+
154
+ assert_trace pdef, 'AA'
155
+ end
156
+
157
+ def test_wfid
158
+
159
+ pdef = Ruote.process_definition do
160
+ sequence do
161
+ echo '${fei}'
162
+ echo '${wfid}'
163
+ end
164
+ end
165
+
166
+ wfid = @engine.launch(pdef)
167
+
168
+ @engine.wait_for(wfid)
169
+
170
+ assert_equal "0_0_0!!#{wfid}\n#{wfid}", @tracer.to_s
171
+ end
89
172
  end
90
173
 
@@ -432,5 +432,48 @@ class FtProcessStatusTest < Test::Unit::TestCase
432
432
  assert_equal 'alpha', h['participant_name']
433
433
  assert_equal ["participant", {"ref"=>"alpha"}, []], h['original_tree']
434
434
  end
435
+
436
+ def test_to_dot
437
+
438
+ pdef = Ruote.process_definition :name => 'my process' do
439
+ concurrence do
440
+ participant :ref => 'alpha'
441
+ participant :ref => 'bravo'
442
+ end
443
+ end
444
+
445
+ alpha = @engine.register_participant :alpha, Ruote::HashParticipant.new
446
+
447
+ wfid = @engine.launch(pdef)
448
+
449
+ wait_for(:alpha)
450
+
451
+ ps = @engine.process(wfid)
452
+
453
+ #puts
454
+ #puts ps.to_dot
455
+
456
+ dot = ps.to_dot
457
+ dot = dot.gsub(wfid, 'wfid').strip
458
+
459
+ assert_equal(
460
+ %{
461
+ digraph "process wfid wfid" {
462
+ "0!!wfid" [ label="wfid 0 define" ];
463
+ "0!!wfid" -> "0_0!!wfid";
464
+ "0_0!!wfid" [ label="wfid 0_0 concurrence" ];
465
+ "0_0!!wfid" -> "0!!wfid";
466
+ "0_0!!wfid" -> "0_0_0!!wfid";
467
+ "0_0!!wfid" -> "0_0_1!!wfid";
468
+ "0_0_0!!wfid" [ label="wfid 0_0_0 participant" ];
469
+ "0_0_0!!wfid" -> "0_0!!wfid";
470
+ "0_0_1!!wfid" [ label="wfid 0_0_1 participant" ];
471
+ "0_0_1!!wfid" -> "0_0!!wfid";
472
+ "err_0_0_1!!wfid" [ label = "error : #<ArgumentError: no participant named 'bravo'>" ];
473
+ "err_0_0_1!!wfid" -> "0_0_1!!wfid" [ style = "dotted" ];
474
+ }
475
+ }.strip,
476
+ dot)
477
+ end
435
478
  end
436
479
 
@@ -36,6 +36,10 @@ class FtStorageParticipantTest < Test::Unit::TestCase
36
36
 
37
37
  assert_equal Ruote::Workitem, wi.class
38
38
 
39
+ wi = alpha[alpha.first.fei]
40
+
41
+ assert_equal Ruote::Workitem, wi.class
42
+
39
43
  alpha.reply(wi)
40
44
 
41
45
  wait_for(wfid)
@@ -93,19 +97,27 @@ class FtStorageParticipantTest < Test::Unit::TestCase
93
97
  assert_equal 2, alpha.by_wfid(wfid).size
94
98
  end
95
99
 
96
- def test_find_by_participant
97
-
98
- pdef = Ruote.process_definition :name => 'def0' do
99
- concurrence do
100
+ CON_AL_BRAVO = Ruote.process_definition :name => 'con_al_bravo' do
101
+ set 'f:place' => 'heiankyou'
102
+ concurrence do
103
+ sequence do
104
+ set 'f:character' => 'minamoto no hirosama'
100
105
  alpha
106
+ end
107
+ sequence do
108
+ set 'f:character' => 'seimei'
109
+ set 'f:adversary' => 'doson'
101
110
  bravo
102
111
  end
103
112
  end
113
+ end
114
+
115
+ def test_find_by_participant
104
116
 
105
117
  @engine.register_participant :alpha, Ruote::StorageParticipant
106
118
  @engine.register_participant :bravo, Ruote::StorageParticipant
107
119
 
108
- wfid = @engine.launch(pdef)
120
+ wfid = @engine.launch(CON_AL_BRAVO)
109
121
 
110
122
  wait_for(:bravo)
111
123
 
@@ -116,5 +128,112 @@ class FtStorageParticipantTest < Test::Unit::TestCase
116
128
  assert_equal 1, part.by_participant('alpha').size
117
129
  assert_equal 1, part.by_participant('bravo').size
118
130
  end
131
+
132
+ def test_by_field
133
+
134
+ @engine.register_participant :alpha, Ruote::StorageParticipant
135
+ @engine.register_participant :bravo, Ruote::StorageParticipant
136
+
137
+ wfid = @engine.launch(CON_AL_BRAVO)
138
+
139
+ wait_for(:bravo)
140
+
141
+ part = Ruote::StorageParticipant.new
142
+ part.context = @engine.context
143
+
144
+ assert_equal 2, part.size
145
+ assert_equal 2, part.by_field('place').size
146
+ assert_equal 2, part.by_field('character').size
147
+ assert_equal 1, part.by_field('adversary').size
148
+ end
149
+
150
+ def test_by_field_and_value
151
+
152
+ @engine.register_participant :alpha, Ruote::StorageParticipant
153
+ @engine.register_participant :bravo, Ruote::StorageParticipant
154
+
155
+ wfid = @engine.launch(CON_AL_BRAVO)
156
+
157
+ wait_for(:bravo)
158
+
159
+ part = Ruote::StorageParticipant.new
160
+ part.context = @engine.context
161
+
162
+ assert_equal 2, part.size
163
+ assert_equal 0, part.by_field('place', 'nara').size
164
+ assert_equal 2, part.by_field('place', 'heiankyou').size
165
+ assert_equal 1, part.by_field('character', 'minamoto no hirosama').size
166
+ end
167
+
168
+ def test_initialize_engine_then_opts
169
+
170
+ @engine.register_participant :alpha, Ruote::StorageParticipant
171
+
172
+ wfid = @engine.launch(Ruote.process_definition do
173
+ alpha
174
+ end)
175
+
176
+ wait_for(:alpha)
177
+
178
+ part = Ruote::StorageParticipant.new(@engine)
179
+
180
+ assert_equal 1, part.size
181
+ end
182
+
183
+ def test_cancel
184
+
185
+ pdef = Ruote.process_definition :name => 'def0' do
186
+ alpha
187
+ end
188
+
189
+ @engine.register_participant :alpha, Ruote::StorageParticipant
190
+
191
+ #noisy
192
+
193
+ wfid = @engine.launch(pdef)
194
+
195
+ wait_for(:alpha)
196
+
197
+ @engine.cancel_process(wfid)
198
+
199
+ wait_for(wfid)
200
+
201
+ assert_nil @engine.process(wfid)
202
+ assert_equal 0, Ruote::StorageParticipant.new(@engine).size
203
+ end
204
+
205
+ def test_shared_participant
206
+
207
+ @engine.register_participant 'step_.*', Ruote::StorageParticipant
208
+
209
+ wfid = @engine.launch(
210
+ Ruote.process_definition { sequence { step_one; step_two } })
211
+
212
+ wait_for(:step_one)
213
+
214
+ participant = Ruote::StorageParticipant.new(@engine)
215
+
216
+ items = participant.by_wfid(wfid)
217
+
218
+ assert_equal 1, participant.size
219
+ assert_equal 1, items.size
220
+ assert_equal 'step_one', items.first.participant_name
221
+
222
+ participant.reply(items.first)
223
+
224
+ wait_for(:step_two)
225
+
226
+ items = participant.by_wfid(wfid)
227
+
228
+ assert_equal 1, participant.size
229
+ assert_equal 1, items.size
230
+ assert_equal 'step_two', items.first.participant_name
231
+
232
+ participant.reply(items.first)
233
+
234
+ wait_for(wfid)
235
+
236
+ assert_nil @engine.process(wfid)
237
+ end
119
238
  end
120
239