ruote 2.3.0.1 → 2.3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/CHANGELOG.txt +23 -0
  2. data/CREDITS.txt +4 -0
  3. data/LICENSE.txt +1 -1
  4. data/lib/ruote.rb +2 -0
  5. data/lib/ruote/context.rb +2 -1
  6. data/lib/ruote/dashboard.rb +169 -13
  7. data/lib/ruote/dboard/mutation.rb +282 -0
  8. data/lib/ruote/dboard/process_error.rb +1 -1
  9. data/lib/ruote/dboard/process_status.rb +61 -48
  10. data/lib/ruote/engine.rb +1 -1
  11. data/lib/ruote/exp/command.rb +1 -1
  12. data/lib/ruote/exp/commanded.rb +1 -1
  13. data/lib/ruote/exp/condition.rb +2 -1
  14. data/lib/ruote/exp/fe_add_branches.rb +1 -1
  15. data/lib/ruote/exp/fe_apply.rb +1 -1
  16. data/lib/ruote/exp/fe_await.rb +97 -48
  17. data/lib/ruote/exp/fe_cancel_process.rb +1 -1
  18. data/lib/ruote/exp/fe_command.rb +2 -3
  19. data/lib/ruote/exp/fe_concurrence.rb +162 -66
  20. data/lib/ruote/exp/fe_concurrent_iterator.rb +25 -7
  21. data/lib/ruote/exp/fe_cron.rb +1 -1
  22. data/lib/ruote/exp/fe_cursor.rb +10 -11
  23. data/lib/ruote/exp/fe_define.rb +1 -1
  24. data/lib/ruote/exp/fe_echo.rb +1 -1
  25. data/lib/ruote/exp/fe_equals.rb +1 -1
  26. data/lib/ruote/exp/fe_error.rb +1 -1
  27. data/lib/ruote/exp/fe_filter.rb +1 -1
  28. data/lib/ruote/exp/fe_forget.rb +1 -1
  29. data/lib/ruote/exp/fe_given.rb +1 -1
  30. data/lib/ruote/exp/fe_if.rb +87 -7
  31. data/lib/ruote/exp/fe_inc.rb +1 -1
  32. data/lib/ruote/exp/fe_iterator.rb +1 -1
  33. data/lib/ruote/exp/fe_listen.rb +1 -1
  34. data/lib/ruote/exp/fe_lose.rb +1 -1
  35. data/lib/ruote/exp/fe_noop.rb +1 -1
  36. data/lib/ruote/exp/fe_on_error.rb +1 -1
  37. data/lib/ruote/exp/fe_once.rb +1 -1
  38. data/lib/ruote/exp/fe_participant.rb +49 -16
  39. data/lib/ruote/exp/fe_read.rb +1 -1
  40. data/lib/ruote/exp/fe_redo.rb +1 -1
  41. data/lib/ruote/exp/fe_ref.rb +1 -1
  42. data/lib/ruote/exp/fe_registerp.rb +1 -1
  43. data/lib/ruote/exp/fe_reserve.rb +1 -1
  44. data/lib/ruote/exp/fe_restore.rb +1 -7
  45. data/lib/ruote/exp/fe_save.rb +1 -1
  46. data/lib/ruote/exp/fe_sequence.rb +1 -1
  47. data/lib/ruote/exp/fe_set.rb +1 -1
  48. data/lib/ruote/exp/fe_stall.rb +1 -1
  49. data/lib/ruote/exp/fe_subprocess.rb +1 -1
  50. data/lib/ruote/exp/fe_that.rb +1 -1
  51. data/lib/ruote/exp/fe_undo.rb +1 -1
  52. data/lib/ruote/exp/fe_unregisterp.rb +1 -1
  53. data/lib/ruote/exp/fe_wait.rb +1 -1
  54. data/lib/ruote/exp/flow_expression.rb +117 -8
  55. data/lib/ruote/exp/iterator.rb +1 -1
  56. data/lib/ruote/exp/ro_attributes.rb +1 -1
  57. data/lib/ruote/exp/ro_filters.rb +1 -1
  58. data/lib/ruote/exp/ro_on_x.rb +4 -2
  59. data/lib/ruote/exp/ro_persist.rb +1 -1
  60. data/lib/ruote/exp/ro_timers.rb +1 -1
  61. data/lib/ruote/exp/ro_variables.rb +1 -1
  62. data/lib/ruote/extract.rb +125 -0
  63. data/lib/ruote/fei.rb +10 -73
  64. data/lib/ruote/id/mnemo_wfid_generator.rb +1 -1
  65. data/lib/ruote/id/wfid_generator.rb +1 -1
  66. data/lib/ruote/log/default_history.rb +17 -3
  67. data/lib/ruote/log/fancy_printing.rb +12 -32
  68. data/lib/ruote/log/storage_history.rb +1 -1
  69. data/lib/ruote/log/wait_logger.rb +15 -7
  70. data/lib/ruote/merge.rb +123 -0
  71. data/lib/ruote/observer.rb +1 -1
  72. data/lib/ruote/part/block_participant.rb +1 -1
  73. data/lib/ruote/part/code_participant.rb +1 -1
  74. data/lib/ruote/part/engine_participant.rb +1 -1
  75. data/lib/ruote/part/local_participant.rb +9 -1
  76. data/lib/ruote/part/no_op_participant.rb +1 -1
  77. data/lib/ruote/part/null_participant.rb +1 -1
  78. data/lib/ruote/part/participant.rb +1 -1
  79. data/lib/ruote/part/rev_participant.rb +1 -1
  80. data/lib/ruote/part/smtp_participant.rb +1 -1
  81. data/lib/ruote/part/storage_participant.rb +18 -1
  82. data/lib/ruote/part/template.rb +1 -1
  83. data/lib/ruote/reader.rb +1 -1
  84. data/lib/ruote/reader/json.rb +1 -1
  85. data/lib/ruote/reader/radial.rb +4 -4
  86. data/lib/ruote/reader/ruby_dsl.rb +1 -1
  87. data/lib/ruote/reader/xml.rb +1 -1
  88. data/lib/ruote/receiver/base.rb +13 -1
  89. data/lib/ruote/storage/base.rb +8 -14
  90. data/lib/ruote/storage/composite_storage.rb +1 -1
  91. data/lib/ruote/storage/fs_storage.rb +1 -1
  92. data/lib/ruote/storage/hash_storage.rb +2 -1
  93. data/lib/ruote/svc/dispatch_pool.rb +29 -18
  94. data/lib/ruote/svc/dollar_sub.rb +5 -8
  95. data/lib/ruote/svc/error_handler.rb +1 -1
  96. data/lib/ruote/svc/expression_map.rb +1 -1
  97. data/lib/ruote/svc/participant_list.rb +8 -5
  98. data/lib/ruote/svc/tracker.rb +154 -56
  99. data/lib/ruote/svc/treechecker.rb +1 -1
  100. data/lib/ruote/tree_dot.rb +1 -1
  101. data/lib/ruote/util/deep.rb +4 -2
  102. data/lib/ruote/util/filter.rb +1 -1
  103. data/lib/ruote/util/hashdot.rb +1 -1
  104. data/lib/ruote/util/look.rb +1 -1
  105. data/lib/ruote/util/lookup.rb +1 -1
  106. data/lib/ruote/util/misc.rb +51 -1
  107. data/lib/ruote/util/mpatch.rb +1 -1
  108. data/lib/ruote/util/ometa.rb +1 -1
  109. data/lib/ruote/util/subprocess.rb +1 -1
  110. data/lib/ruote/util/time.rb +3 -3
  111. data/lib/ruote/util/tree.rb +43 -4
  112. data/lib/ruote/version.rb +2 -2
  113. data/lib/ruote/worker.rb +30 -18
  114. data/lib/ruote/workitem.rb +1 -1
  115. data/ruote.gemspec +6 -2
  116. data/test/functional/base.rb +0 -1
  117. data/test/functional/concurrent_base.rb +1 -1
  118. data/test/functional/eft_14_cursor.rb +42 -52
  119. data/test/functional/eft_16_if.rb +24 -16
  120. data/test/functional/eft_18_concurrent_iterator.rb +31 -1
  121. data/test/functional/eft_6_concurrence.rb +149 -34
  122. data/test/functional/ft_10_dollar.rb +14 -30
  123. data/test/functional/ft_12_launchitem.rb +15 -0
  124. data/test/functional/ft_1_process_status.rb +62 -13
  125. data/test/functional/ft_20_storage_participant.rb +25 -0
  126. data/test/functional/ft_38_participant_more.rb +1 -1
  127. data/test/functional/ft_42_storage_copy.rb +1 -3
  128. data/test/functional/ft_43_participant_on_reply.rb +63 -5
  129. data/test/functional/ft_66_flank.rb +41 -0
  130. data/test/functional/ft_6_on_cancel.rb +9 -18
  131. data/test/functional/ft_71_retries.rb +25 -12
  132. data/test/functional/ft_79_attach.rb +138 -0
  133. data/test/functional/ft_7_tags.rb +27 -0
  134. data/test/functional/ft_80_pause_on_apply.rb +64 -0
  135. data/test/functional/ft_81_mutation.rb +417 -0
  136. data/test/functional/ft_82_await_attribute.rb +84 -0
  137. data/test/functional/ft_83_trackers.rb +79 -0
  138. data/test/functional/storage.rb +3 -4
  139. data/test/unit/ut_12_wait_logger.rb +41 -3
  140. data/test/unit/ut_15_util.rb +30 -0
  141. data/test/unit/ut_17_merge.rb +54 -53
  142. data/test/unit/ut_1_fei.rb +2 -2
  143. data/test/unit/ut_24_radial_reader.rb +7 -0
  144. data/test/unit/ut_26_deep.rb +14 -0
  145. data/test/unit/ut_5_tree.rb +38 -28
  146. metadata +206 -169
  147. data/couch_url.txt +0 -1
  148. data/lib/ruote/exp/merge.rb +0 -134
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -114,9 +114,8 @@ module Ruote::Exp
114
114
 
115
115
  fei = lookup_variable(ref)
116
116
 
117
- target = Ruote::FlowExpressionId.is_a_fei?(fei) ?
117
+ target = Ruote.is_a_fei?(fei) ?
118
118
  Ruote::Exp::FlowExpression.fetch(@context, fei) : nil
119
-
120
119
  target = target.is_a?(Ruote::Exp::CommandedExpression) ?
121
120
  target : nil
122
121
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -22,8 +22,7 @@
22
22
  # Made in Japan.
23
23
  #++
24
24
 
25
-
26
- require 'ruote/exp/merge'
25
+ require 'ruote/merge'
27
26
 
28
27
 
29
28
  module Ruote::Exp
@@ -94,6 +93,25 @@ module Ruote::Exp
94
93
  #
95
94
  # :wait_for can be shortened to :wf.
96
95
  #
96
+ #
97
+ # === :over_if (and :over_unless) attribute
98
+ #
99
+ # Like the :count attribute controls how many branches have to reply before
100
+ # a concurrence ends, the :over attribute is used to specify a condition
101
+ # upon which the concurrence will [prematurely] end.
102
+ #
103
+ # concurrence :over_if => '${f:over}'
104
+ # alpha
105
+ # bravo
106
+ # charly
107
+ # end
108
+ #
109
+ # will end the concurrence as soon as one of the branches replies with a
110
+ # workitem whose field 'over' is set to true. (the remaining branches will
111
+ # get cancelled unless :remaining => :forget is set).
112
+ #
113
+ # :over_unless needs no explanation.
114
+ #
97
115
  # === :remaining
98
116
  #
99
117
  # As said for :count, the remaining branches get cancelled. By setting
@@ -152,23 +170,23 @@ module Ruote::Exp
152
170
  #
153
171
  # === :merge_type
154
172
  #
155
- # ==== :override
173
+ # ==== :merge_type => :override (default)
156
174
  #
157
175
  # By default, the merge type is set to 'override', which means that the
158
176
  # 'winning' workitem's payload supplants all other workitems' payloads.
159
177
  #
160
- # ==== :mix
178
+ # ==== :merge_type => :mix
161
179
  #
162
180
  # Setting :merge_type to :mix, will actually attempt to merge field by field,
163
181
  # making sure that the field value of the winner(s) are used.
164
182
  #
165
- # ==== :isolate
183
+ # ==== :merge_type => :isolate
166
184
  #
167
185
  # :isolate will rearrange the resulting workitem payload so that there is
168
186
  # a new field for each branch. The name of each field is the index of the
169
187
  # branch from '0' to ...
170
188
  #
171
- # ==== :stack
189
+ # ==== :merge_type => :stack
172
190
  #
173
191
  # :stack will stack the workitems coming back from the concurrence branches
174
192
  # in an array whose order is determined by the :merge attributes. The array
@@ -194,7 +212,7 @@ module Ruote::Exp
194
212
  # This could prove useful for participant having to deal with multiple merge
195
213
  # strategy results.
196
214
  #
197
- # ==== :union
215
+ # ==== :merge_type => :union
198
216
  #
199
217
  # (Available from ruote 2.3.0)
200
218
  #
@@ -214,7 +232,7 @@ module Ruote::Exp
214
232
  # Warning: duplicates in arrays present _before_ the merge will be removed
215
233
  # as well.
216
234
  #
217
- # ==== :concat
235
+ # ==== :merge_type => :concat
218
236
  #
219
237
  # (Available from ruote 2.3.0)
220
238
  #
@@ -229,14 +247,14 @@ module Ruote::Exp
229
247
  # 'b' => [ 'x', 'y', 'y', 'z' ],
230
248
  # 'c' => { 'aa' => 'bb', 'cc' => 'dd' } }
231
249
  #
232
- # ==== :deep
250
+ # ==== :merge_type => :deep
233
251
  #
234
252
  # (Available from ruote 2.3.0)
235
253
  #
236
254
  # Identical to :concat but hashes are merged with deep_merge (ActiveSupport
237
255
  # flavour).
238
256
  #
239
- # ==== :ignore
257
+ # ==== :merge_type => :ignore
240
258
  #
241
259
  # (Available from ruote 2.3.0)
242
260
  #
@@ -246,33 +264,20 @@ module Ruote::Exp
246
264
  #
247
265
  # :merge_type can be shortened to :mt.
248
266
  #
249
- #
250
- # === :over_if (and :over_unless) attribute
251
- #
252
- # Like the :count attribute controls how many branches have to reply before
253
- # a concurrence ends, the :over attribute is used to specify a condition
254
- # upon which the concurrence will [prematurely] end.
255
- #
256
- # concurrence :over_if => '${f:over}'
257
- # alpha
258
- # bravo
259
- # charly
260
- # end
261
- #
262
- # will end the concurrence as soon as one of the branches replies with a
263
- # workitem whose field 'over' is set to true. (the remaining branches will
264
- # get cancelled unless :remaining => :forget is set).
265
- #
266
- # :over_unless needs no explanation.
267
- #
268
267
  class ConcurrenceExpression < FlowExpression
269
268
 
270
- include MergeMixin
271
-
272
269
  names :concurrence
273
270
 
274
271
  COUNT_R = /^-?\d+$/
275
272
 
273
+ # This method is used by some walking routines when analyzsing
274
+ # execution trees. Returns true for concurrence (and concurrent iterator).
275
+ #
276
+ def is_concurrent?
277
+
278
+ true
279
+ end
280
+
276
281
  def apply
277
282
 
278
283
  return do_reply_to_parent(h.applied_workitem) if tree_children.empty?
@@ -304,7 +309,14 @@ module Ruote::Exp
304
309
  [ :remaining, :rem, :r ],
305
310
  %w[ cancel forget wait ])
306
311
 
307
- h.workitems = (h.cmerge == 'first' || h.cmerge == 'last') ? [] : {}
312
+ #h.workitems = (h.cmerge == 'first' || h.cmerge == 'last') ? [] : {}
313
+ #
314
+ # now merging iteratively, not keeping track of all the workitems,
315
+ # but still able to deal with old flows with active h.workitems
316
+ #
317
+ h.workitems = [] if %w[ highest lowest ].include?(h.cmerge)
318
+ #
319
+ # still need to keep track of rank to get the right merging
308
320
 
309
321
  h.over = false
310
322
 
@@ -325,12 +337,6 @@ module Ruote::Exp
325
337
  # a copy of the workitem (so that history, coming afterwards,
326
338
  # doesn't see a modified version of the workitem)
327
339
 
328
- if h.cmerge == 'first' || h.cmerge == 'last'
329
- h.workitems << workitem
330
- else
331
- h.workitems[workitem['fei']['expid']] = workitem
332
- end
333
-
334
340
  if h.wait_for && tag = workitem['fields']['__left_tag__']
335
341
  h.wait_for.delete(tag)
336
342
  end
@@ -338,7 +344,11 @@ module Ruote::Exp
338
344
  over = h.over
339
345
  h.over = over || over?(workitem)
340
346
 
347
+ keep(workitem)
348
+ # is done after the over? determination for its looks at 'winner'
349
+
341
350
  if (not over) && h.over
351
+ #
342
352
  # just became 'over'
343
353
 
344
354
  reply_to_parent(nil)
@@ -362,6 +372,42 @@ module Ruote::Exp
362
372
 
363
373
  protected
364
374
 
375
+ def keep(workitem)
376
+
377
+ h.workitems = h.workitems.values if h.workitems.is_a?(Hash)
378
+ # align legacy expressions on new simplified way
379
+
380
+ if h.workitems
381
+ #
382
+ # the old way (still used for highest / lowest)
383
+
384
+ h.workitems << workitem
385
+ return
386
+ end
387
+
388
+ #
389
+ # the new way, merging immediately
390
+
391
+ h.workitem_count = (h.workitem_count || 0) + 1
392
+
393
+ return if h.cmerge_type == 'ignore'
394
+
395
+ # preparing target and source in the right order for merging
396
+
397
+ target, source = h.workitem, workitem
398
+ if
399
+ h.cmerge == 'first' &&
400
+ ! %w[ stack union concat deep isolate ].include?(h.cmerge_type)
401
+ then
402
+ target, source = source, target
403
+ end
404
+ target, source = source, target if target && target.delete('winner')
405
+ target, source = source, target if source == nil
406
+
407
+ h.workitem = Ruote.merge_workitem(
408
+ workitem_index(workitem), target, source, h.cmerge_type)
409
+ end
410
+
365
411
  def apply_children
366
412
 
367
413
  # a) register children
@@ -393,7 +439,8 @@ module Ruote::Exp
393
439
  elsif h.wait_for
394
440
  h.wait_for.empty?
395
441
  else
396
- (h.workitems.size >= expected_count)
442
+ (workitem_count + 1 >= expected_count)
443
+ # the + 1 is necessary since #keep hasn't yet been called
397
444
  end
398
445
  end
399
446
 
@@ -425,13 +472,13 @@ module Ruote::Exp
425
472
 
426
473
  if h.remaining == 'wait'
427
474
 
428
- if h.workitems.size >= count_list_size
475
+ if workitem_count >= count_list_size
429
476
  #
430
477
  # all children have replied
431
478
 
432
- workitem = merge_all_workitems
479
+ h.workitem = final_merge
433
480
 
434
- do_unpersist && super(workitem, false)
481
+ do_unpersist && super(h.workitem, false)
435
482
 
436
483
  elsif h.children_cancelled == nil
437
484
  #
@@ -450,17 +497,17 @@ module Ruote::Exp
450
497
  #
451
498
  # remaining 'forget' and 'cancel' cases
452
499
 
453
- workitem = merge_all_workitems
500
+ h.workitem = final_merge
454
501
 
455
502
  if h.children.empty?
456
503
 
457
- do_unpersist && super(workitem, false)
504
+ do_unpersist && super(h.workitem, false)
458
505
 
459
506
  elsif h.remaining == 'cancel'
460
507
 
461
508
  if do_unpersist
462
509
 
463
- super(workitem, false)
510
+ super(h.workitem, false)
464
511
 
465
512
  h.children.each { |i| @context.storage.put_msg('cancel', 'fei' => i) }
466
513
  end
@@ -470,35 +517,84 @@ module Ruote::Exp
470
517
  h.variables = compile_variables
471
518
  h.forgotten = true
472
519
 
473
- do_persist && super(workitem, false)
520
+ do_persist && super(h.workitem, false)
474
521
  end
475
522
  end
476
523
 
477
524
  # Called by #reply_to_parent, returns the unique, merged, workitem that
478
525
  # will be fed back to the parent expression.
479
526
  #
480
- def merge_all_workitems
481
-
482
- return h.applied_workitem if h.workitems.size < 1
483
- return h.applied_workitem if h.cmerge_type == 'ignore'
484
-
485
- wis = case h.cmerge
486
- when 'first'
487
- h.workitems.reverse
488
- when 'last'
489
- h.workitems
490
- when 'highest', 'lowest'
491
- is = h.workitems.keys.sort.collect { |k| h.workitems[k] }
492
- h.cmerge == 'highest' ? is.reverse : is
527
+ def final_merge
528
+
529
+ wi = if h.workitem
530
+
531
+ h.workitem
532
+
533
+ elsif h.cmerge_type == 'ignore' || h.workitems.nil? || h.workitems.empty?
534
+
535
+ h.applied_workitem
536
+
537
+ else
538
+
539
+ wis = h.workitems
540
+
541
+ if %w[ highest lowest ].include?(h.cmerge)
542
+ wis = h.workitems.sort_by { |wi| wi['fei']['expid'] }
543
+ end
544
+
545
+ if
546
+ %w[ first highest ].include?(h.cmerge) &&
547
+ ! %w[ stack union concat deep ].include?(h.cmerge_type)
548
+ then
549
+ wis = wis.reverse
550
+ end
551
+
552
+ as, bs = wis.partition { |wi| wi.delete('winner') }
553
+ wis = bs + as
554
+ #
555
+ # the 'winner' is the workitem that triggered successfully the
556
+ # :over_if or :over_unless, let's take him precedence in the merge...
557
+
558
+ merge_workitems(wis, h.cmerge_type)
493
559
  end
494
560
 
495
- as, bs = wis.partition { |wi| wi.delete('winner') }
496
- wis = bs + as
497
- #
498
- # the 'winner' is the workitem that triggered successfully the
499
- # :over_if or :over_unless, let's take him precedence in the merge...
561
+ if h.cmerge_type == 'stack'
562
+ wi['fields']['stack_attributes'] = compile_atts
563
+ end
564
+
565
+ wi
566
+ end
567
+
568
+ # Returns the current count of workitem replies.
569
+ #
570
+ def workitem_count
500
571
 
501
- merge_workitems(wis, h.cmerge_type)
572
+ h.workitems ? h.workitems.size : (h.workitem_count || 0)
573
+ end
574
+
575
+ # Given a workitem, returns its index (highest to lowest in the tree
576
+ # children... z-index?).
577
+ #
578
+ # Is overriden by the concurrent-iterator.
579
+ #
580
+ def workitem_index(workitem)
581
+
582
+ Ruote.extract_child_id(workitem['fei'])
583
+ end
584
+
585
+ # Given a list of workitems and a merge_type, will merge according to
586
+ # the merge type.
587
+ #
588
+ # The return value is the merged workitem.
589
+ #
590
+ # (Still used when dealing with highest/lowest merge_type and legacy
591
+ # concurrence/citerator expressions)
592
+ #
593
+ def merge_workitems(workitems, merge_type)
594
+
595
+ workitems.inject(nil) do |t, wi|
596
+ Ruote.merge_workitem(workitem_index(wi), t, wi, merge_type)
597
+ end
502
598
  end
503
599
  end
504
600
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -150,8 +150,8 @@ module Ruote::Exp
150
150
  # the concurrent_iterator accepts the same options for merging as its bigger
151
151
  # brother, the concurrence expression.
152
152
  #
153
- # :count, :merge (override, mix, isolate), remaining (cancel, forget) and
154
- # :over.
153
+ # :count, :merge (override, mix, isolate, stack, union, concat, deep, ignore),
154
+ # :remaining (cancel, forget) and :over.
155
155
  #
156
156
  #
157
157
  # == add branches
@@ -228,7 +228,11 @@ module Ruote::Exp
228
228
  end
229
229
 
230
230
  launch_sub(
231
- expid, subtree, :workitem => workitem, :variables => variables)
231
+ expid,
232
+ subtree,
233
+ :workitem => workitem,
234
+ :variables => variables,
235
+ :child_id => h.list_size - 1)
232
236
  end
233
237
  end
234
238
 
@@ -238,9 +242,10 @@ module Ruote::Exp
238
242
 
239
243
  add_branches(ab)
240
244
 
241
- if h.fei['wfid'] != workitem['fei']['wfid'] ||
242
- ( ! workitem['fei']['expid'].match(/^#{h.fei['expid']}_\d+$/))
243
-
245
+ if
246
+ h.fei['wfid'] != workitem['fei']['wfid'] ||
247
+ ( ! workitem['fei']['expid'].match(/^#{h.fei['expid']}_\d+$/))
248
+ then
244
249
  do_persist
245
250
  return
246
251
  end
@@ -275,6 +280,19 @@ module Ruote::Exp
275
280
 
276
281
  h.list_size
277
282
  end
283
+
284
+ # TODO
285
+ #
286
+ def workitem_index(workitem)
287
+
288
+ if %w[ highest lowest ].include?(h.cmerge)
289
+ nil
290
+ elsif m = workitem['fei']['subid'].match(/k(\d)+$/)
291
+ m[1].to_i
292
+ else
293
+ nil
294
+ end
295
+ end
278
296
  end
279
297
  end
280
298