openwferu 0.9.16 → 0.9.17

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.
Files changed (184) hide show
  1. data/examples/about_state.rb +81 -0
  2. data/examples/engine_template.rb +7 -0
  3. data/lib/openwfe/contextual.rb +2 -2
  4. data/lib/openwfe/def.rb +2 -3
  5. data/lib/openwfe/{util/schedulers.rb → engine.rb} +3 -39
  6. data/lib/openwfe/engine/engine.rb +202 -251
  7. data/lib/openwfe/engine/process_status.rb +359 -0
  8. data/lib/openwfe/expool/errorjournal.rb +6 -6
  9. data/lib/openwfe/expool/expressionpool.rb +161 -239
  10. data/lib/openwfe/expool/expstorage.rb +185 -55
  11. data/lib/openwfe/expool/journal.rb +1 -2
  12. data/lib/openwfe/expool/parser.rb +233 -0
  13. data/lib/openwfe/expool/threadedexpstorage.rb +6 -18
  14. data/lib/openwfe/expool/wfidgen.rb +25 -7
  15. data/lib/openwfe/expool/yamlexpstorage.rb +60 -37
  16. data/lib/openwfe/expressions/condition.rb +49 -12
  17. data/lib/openwfe/expressions/environment.rb +45 -15
  18. data/lib/openwfe/expressions/expressionmap.rb +39 -19
  19. data/lib/openwfe/expressions/fe_concurrence.rb +24 -13
  20. data/lib/openwfe/expressions/fe_cron.rb +19 -18
  21. data/lib/openwfe/expressions/fe_cursor.rb +69 -28
  22. data/lib/openwfe/expressions/fe_define.rb +4 -1
  23. data/lib/openwfe/expressions/fe_do.rb +1 -3
  24. data/lib/openwfe/expressions/fe_equals.rb +131 -20
  25. data/lib/openwfe/expressions/fe_fqv.rb +27 -3
  26. data/lib/openwfe/expressions/fe_iterator.rb +14 -7
  27. data/lib/openwfe/expressions/fe_listen.rb +7 -2
  28. data/lib/openwfe/expressions/fe_misc.rb +187 -20
  29. data/lib/openwfe/expressions/fe_participant.rb +8 -7
  30. data/lib/openwfe/expressions/fe_reserve.rb +105 -33
  31. data/lib/openwfe/expressions/fe_save.rb +55 -5
  32. data/lib/openwfe/expressions/{fe_value.rb → fe_set.rb} +6 -82
  33. data/lib/openwfe/expressions/fe_sleep.rb +25 -15
  34. data/lib/openwfe/expressions/fe_subprocess.rb +2 -2
  35. data/lib/openwfe/expressions/fe_wait.rb +3 -2
  36. data/lib/openwfe/expressions/fe_when.rb +7 -15
  37. data/lib/openwfe/expressions/flowexpression.rb +90 -49
  38. data/lib/openwfe/expressions/merge.rb +7 -1
  39. data/lib/openwfe/expressions/raw.rb +261 -63
  40. data/lib/openwfe/expressions/{raw_prog.rb → rprocdef.rb} +94 -179
  41. data/lib/openwfe/expressions/time.rb +36 -12
  42. data/lib/openwfe/expressions/timeout.rb +9 -7
  43. data/lib/openwfe/expressions/value.rb +126 -0
  44. data/lib/openwfe/flowexpressionid.rb +52 -22
  45. data/lib/openwfe/listeners/listeners.rb +3 -3
  46. data/lib/openwfe/listeners/socketlisteners.rb +8 -5
  47. data/lib/openwfe/logging.rb +6 -3
  48. data/lib/openwfe/omixins.rb +8 -6
  49. data/lib/openwfe/orest/xmlcodec.rb +16 -12
  50. data/lib/openwfe/participants.rb +38 -0
  51. data/lib/openwfe/participants/participant.rb +1 -1
  52. data/lib/openwfe/participants/participantmap.rb +24 -10
  53. data/lib/openwfe/participants/participants.rb +4 -3
  54. data/lib/openwfe/participants/soapparticipants.rb +1 -1
  55. data/lib/openwfe/participants/socketparticipants.rb +1 -1
  56. data/lib/openwfe/rudefinitions.rb +7 -5
  57. data/lib/openwfe/storage/yamlcustom.rb +10 -10
  58. data/lib/openwfe/storage/yamlfilestorage.rb +12 -12
  59. data/lib/openwfe/tools/flowtracer.rb +6 -5
  60. data/lib/openwfe/util/dollar.rb +42 -85
  61. data/lib/openwfe/util/ometa.rb +1 -3
  62. data/lib/openwfe/util/workqueue.rb +1 -1
  63. data/lib/openwfe/utils.rb +33 -11
  64. data/lib/openwfe/version.rb +2 -2
  65. data/lib/openwfe/workitem.rb +76 -14
  66. data/lib/openwfe/worklist/storelocks.rb +9 -4
  67. data/lib/openwfe/worklist/storeparticipant.rb +1 -1
  68. data/test/back_0916_test.rb +101 -0
  69. data/test/bm/ft_26_load.rb +1 -1
  70. data/test/bm/ft_26b_load.rb +1 -1
  71. data/test/bm/ft_26c_load.rb +3 -2
  72. data/test/bm/ft_26d_load.rb +97 -0
  73. data/test/bm/ft_recu.rb +71 -0
  74. data/test/concurrence_test.rb +1 -1
  75. data/test/condition_test.rb +152 -0
  76. data/test/description_test.rb +12 -7
  77. data/test/eno_test.rb +1 -1
  78. data/test/expool_20031219_0916.tgz +0 -0
  79. data/test/fe_lookup_att_test.rb +1 -1
  80. data/test/fei_test.rb +16 -0
  81. data/test/file_persistence_test.rb +8 -12
  82. data/test/filep_cancel_test.rb +116 -0
  83. data/test/flowtestbase.rb +47 -25
  84. data/test/ft_0.rb +1 -1
  85. data/test/ft_10_loop.rb +29 -14
  86. data/test/{ft_10b_loop2.rb → ft_10b_loop.rb} +2 -11
  87. data/test/ft_11_ppd.rb +6 -17
  88. data/test/ft_11b_ppd.rb +1 -4
  89. data/test/ft_12_blockparticipant.rb +1 -1
  90. data/test/ft_13_eno.rb +1 -1
  91. data/test/ft_15_iterator.rb +1 -1
  92. data/test/ft_15b_iterator.rb +1 -1
  93. data/test/ft_17_condition.rb +6 -6
  94. data/test/ft_18_pname.rb +1 -1
  95. data/test/ft_20_cron.rb +1 -1
  96. data/test/ft_21_cron.rb +6 -4
  97. data/test/ft_22_history.rb +1 -1
  98. data/test/ft_23_when.rb +1 -1
  99. data/test/ft_23b_when.rb +18 -6
  100. data/test/ft_23c_wait.rb +8 -6
  101. data/test/ft_25_cancel.rb +7 -5
  102. data/test/ft_27_getflowpos.rb +22 -17
  103. data/test/ft_28_fileparticipant.rb +1 -2
  104. data/test/ft_2_concurrence.rb +1 -1
  105. data/test/ft_2b_concurrence.rb +25 -20
  106. data/test/ft_30_socketlistener.rb +0 -3
  107. data/test/ft_34_cancelwfid.rb +9 -9
  108. data/test/ft_35_localdefs.rb +0 -1
  109. data/test/ft_36_subprocids.rb +6 -6
  110. data/test/ft_38_tag.rb +3 -2
  111. data/test/ft_38b_tag.rb +229 -0
  112. data/test/ft_39_reserve.rb +3 -18
  113. data/test/ft_39b_reserve.rb +34 -5
  114. data/test/ft_3b_lookup_vf.rb +83 -0
  115. data/test/ft_40_defined.rb +2 -11
  116. data/test/ft_42_environments.rb +4 -6
  117. data/test/ft_44b_restore.rb +88 -22
  118. data/test/ft_45_citerator.rb +57 -11
  119. data/test/ft_49_condition.rb +4 -2
  120. data/test/ft_4_misc.rb +24 -3
  121. data/test/ft_50_xml_attribute.rb +17 -20
  122. data/test/ft_54_listen.rb +1 -1
  123. data/test/ft_54b_listen.rb +2 -2
  124. data/test/ft_56_timeout.rb +8 -1
  125. data/test/ft_57_a.rb +10 -10
  126. data/test/ft_59_ps.rb +49 -16
  127. data/test/ft_60_ecancel.rb +52 -10
  128. data/test/ft_63_pause.rb +8 -8
  129. data/test/ft_65_stringlaunch.rb +4 -6
  130. data/test/ft_67_schedlaunch.rb +4 -4
  131. data/test/ft_69_cancelmissing.rb +4 -2
  132. data/test/ft_70_lookupvar.rb +2 -2
  133. data/test/ft_72_lookup_processes.rb +2 -2
  134. data/test/ft_73_cancel_sub.rb +8 -8
  135. data/test/ft_77_segments.rb +38 -0
  136. data/test/ft_78_eval.rb +154 -0
  137. data/test/ft_79_tticket.rb +185 -0
  138. data/test/ft_80_spname.rb +95 -0
  139. data/test/ft_81_exp.rb +64 -0
  140. data/test/ft_82_trecu.rb +48 -0
  141. data/test/ft_83_badpause.rb +62 -0
  142. data/test/ft_84_updateexp.rb +125 -0
  143. data/test/ft_9b_cursor.rb +105 -0
  144. data/test/ft_tests.rb +14 -1
  145. data/test/hash_test.rb +7 -7
  146. data/test/hparticipant_test.rb +4 -4
  147. data/test/lookup_vf_test.rb +94 -0
  148. data/test/misc_test.rb +5 -3
  149. data/test/orest_test.rb +4 -3
  150. data/test/param_test.rb +12 -16
  151. data/test/participant_test.rb +36 -0
  152. data/test/pending.rb +10 -10
  153. data/test/rake_ltest.rb +1 -10
  154. data/test/rake_qtest.rb +7 -6
  155. data/test/raw_prog_test.rb +89 -121
  156. data/test/restart_cron_test.rb +84 -36
  157. data/test/restart_paused_test.rb +100 -0
  158. data/test/restart_sleep_test.rb +1 -1
  159. data/test/restart_tests.rb +1 -0
  160. data/test/restart_when_test.rb +33 -22
  161. data/test/ruby_procdef_test.rb +19 -18
  162. data/test/sec_test.rb +74 -35
  163. data/test/storage_test.rb +44 -0
  164. data/test/test.rb +3 -0
  165. data/test/timeout_test.rb +7 -18
  166. data/test/wfid_test.rb +2 -1
  167. data/test/wi_test.rb +29 -18
  168. metadata +121 -57
  169. data/lib/openwfe/expressions/raw_xml.rb +0 -176
  170. data/lib/openwfe/expressions/simplerep.rb +0 -266
  171. data/lib/openwfe/util/kotoba.rb +0 -236
  172. data/lib/openwfe/util/lru.rb +0 -171
  173. data/lib/openwfe/util/otime.rb +0 -246
  174. data/lib/openwfe/util/safe.rb +0 -160
  175. data/lib/openwfe/util/scheduler.rb +0 -1158
  176. data/test/cron_test.rb +0 -113
  177. data/test/cronline_test.rb +0 -60
  178. data/test/dollar_test.rb +0 -90
  179. data/test/kotoba_test.rb +0 -72
  180. data/test/lru_test.rb +0 -79
  181. data/test/safely_test.rb +0 -84
  182. data/test/scheduler_1_test.rb +0 -88
  183. data/test/scheduler_test.rb +0 -363
  184. data/test/time_test.rb +0 -84
@@ -0,0 +1,81 @@
1
+
2
+ #
3
+ # This is the code used in the blog post :
4
+ # http://jmettraux.wordpress.com/2007/12/03/state-machine/
5
+ #
6
+
7
+
8
+ # some setup
9
+
10
+ require 'openwfe/def'
11
+ require 'openwfe/engine'
12
+ require 'openwfe/participants'
13
+
14
+ engine = OpenWFE::Engine.new
15
+
16
+ alice = engine.register_participant(
17
+ :alice, OpenWFE::HashParticipant)
18
+ bob = engine.register_participant(
19
+ :bob, OpenWFE::HashParticipant)
20
+
21
+ class MyDefinition < OpenWFE::ProcessDefinition
22
+ sequence do
23
+ alice
24
+ bob
25
+ end
26
+ end
27
+
28
+ # later ...
29
+
30
+ #fei = engine.launch MyDefinition
31
+ #
32
+ #sleep 0.050
33
+ # # it's asynchronous, so...
34
+ #
35
+ #puts "alice holds #{alice.size} workitem(s)"
36
+ #puts "bob holds #{bob.size} workitem(s)"
37
+ #
38
+ #puts engine.process_status(fei)
39
+
40
+
41
+ class My2ndDefinition < OpenWFE::ProcessDefinition
42
+ sequence do
43
+ at :state => "redaction"
44
+ alice
45
+ at :state => "correction"
46
+ bob
47
+ alice
48
+ at :state => "approval"
49
+ charly
50
+ end
51
+
52
+ process_definition :name => "at" do
53
+ set :var => "/state", :val => "${state}"
54
+ end
55
+ end
56
+
57
+ #fei = engine.launch My2ndDefinition
58
+ #
59
+ #sleep 0.050
60
+ #
61
+ #puts "state : " + engine.lookup_variable(
62
+ # 'state', fei.workflow_instance_id)
63
+
64
+ class My3rdDefinition < OpenWFE::ProcessDefinition
65
+ sequence do
66
+ alice :tag => "redaction"
67
+ sequence :tag => "correction" do
68
+ bob
69
+ alice
70
+ end
71
+ charly :tag => "approval"
72
+ end
73
+ end
74
+
75
+ fei = engine.launch My3rdDefinition
76
+
77
+ sleep 0.050
78
+
79
+ puts "state : " + engine.process_status(
80
+ fei.workflow_instance_id).tags.inspect
81
+
@@ -47,6 +47,13 @@ require 'openwfe/participants/participants'
47
47
  # <if rtest="var % 2 == 0"> ...
48
48
  #
49
49
 
50
+ #application_context[:dynamic_eval_allowed] = true
51
+ #
52
+ # by default, :dynamic_eval_allowed is not set to true, it means
53
+ # that the "eval" expression cannot be used.
54
+ #
55
+ # don't set that unless you're sure you'll need this 'eval' expression.
56
+
50
57
 
51
58
  #engine = OpenWFE::Engine.new
52
59
  #engine = OpenWFE::Engine.new(application_context)
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2006-2007, John Mettraux, Nicolas Modrzyk OpenWFE.org
3
+ # Copyright (c) 2006-2008, John Mettraux, Nicolas Modrzyk OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -75,7 +75,7 @@ module OpenWFE
75
75
  #
76
76
  def init_service (service_name, service_class)
77
77
 
78
- s = service_class.new(service_name, @application_context)
78
+ s = service_class.new service_name, @application_context
79
79
 
80
80
  unless service_name
81
81
  s.service_name = "#{service_class.name}::#{s.object_id}"
@@ -30,8 +30,6 @@
30
30
  # POSSIBILITY OF SUCH DAMAGE.
31
31
  #++
32
32
  #
33
- # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
- #
35
33
 
36
34
  #
37
35
  # just a redirection
@@ -43,5 +41,6 @@
43
41
  # require 'openwfe/expressions/raw_prog'
44
42
  #
45
43
 
46
- require 'openwfe/expressions/raw_prog'
44
+ require 'openwfe/expressions/rprocdef'
45
+ require 'openwfe/expressions/raw'
47
46
 
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2006-2007, John Mettraux, OpenWFE.org
3
+ # Copyright (c) 2006-2008, John Mettraux, Nicolas Modrzyk OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -31,43 +31,7 @@
31
31
  #++
32
32
  #
33
33
 
34
- #
35
- # "made in Japan"
36
- #
37
- # John Mettraux at openwfe.org
38
- #
39
-
40
- require 'openwfe/service'
41
- require 'openwfe/util/scheduler'
42
-
43
-
44
- module OpenWFE
45
-
46
- #
47
- # The Scheduler class has been made independant of OpenWFE service
48
- # infrastructure (so that one could easily use it without OpenWFE)
49
- #
50
- class SchedulerService < Scheduler
51
- include ServiceMixin, Logging
52
-
53
- def initialize (service_name, application_context)
54
-
55
- super(application_context)
56
-
57
- service_init(service_name, application_context)
58
-
59
- ldebug { "initialize() SchedulerService #{self.object_id}" }
60
-
61
- sstart()
62
- end
63
-
64
- def stop
65
-
66
- linfo { "stop() for scheduler #{self.object_id}" }
67
-
68
- sstop()
69
- end
70
- end
34
+ # just for nicer looking examples
71
35
 
72
- end
36
+ require 'openwfe/engine/engine'
73
37
 
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2006-2007, John Mettraux, Nicolas Modrzyk OpenWFE.org
3
+ # Copyright (c) 2006-2008, John Mettraux, Nicolas Modrzyk OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -41,17 +41,18 @@
41
41
  require 'logger'
42
42
  require 'fileutils'
43
43
 
44
+ require 'rufus/scheduler' # gem 'rufus-scheduler'
45
+
44
46
  require 'openwfe/omixins'
45
47
  require 'openwfe/rudefinitions'
46
48
  require 'openwfe/service'
47
49
  require 'openwfe/workitem'
48
50
  require 'openwfe/util/irb'
49
- require 'openwfe/util/scheduler'
50
- require 'openwfe/util/schedulers'
51
51
  require 'openwfe/expool/wfidgen'
52
52
  require 'openwfe/expool/expressionpool'
53
53
  require 'openwfe/expool/expstorage'
54
54
  require 'openwfe/expool/errorjournal'
55
+ require 'openwfe/engine/process_status'
55
56
  require 'openwfe/expressions/environment'
56
57
  require 'openwfe/expressions/expressionmap'
57
58
  require 'openwfe/participants/participantmap'
@@ -66,6 +67,7 @@ module OpenWFE
66
67
  class Engine < Service
67
68
  include OwfeServiceLocator
68
69
  include FeiMixin
70
+ include StatusMixin
69
71
 
70
72
  #
71
73
  # Builds an OpenWFEru engine.
@@ -79,7 +81,7 @@ module OpenWFE
79
81
  #
80
82
  def initialize (application_context={})
81
83
 
82
- super(S_ENGINE, application_context)
84
+ super S_ENGINE, application_context
83
85
 
84
86
  $OWFE_LOG = application_context[:logger]
85
87
 
@@ -266,13 +268,49 @@ module OpenWFE
266
268
  # This method is a shortcut to the ParticipantMap method
267
269
  # with the same name.
268
270
  #
271
+ # engine.register_participant "user-.*", HashParticipant
272
+ #
273
+ # or
274
+ #
275
+ # engine.register_participant "user-.*" do |wi|
276
+ # puts "participant '#{wi.participant_name}' received a workitem"
277
+ # #
278
+ # # and did nothing with it
279
+ # # as a block participant implicitely returns the workitem
280
+ # # to the engine
281
+ # end
282
+ #
269
283
  # Returns the participant instance.
270
284
  #
285
+ # The participant parameter can be set to hash like in
286
+ #
287
+ # engine.register_participant(
288
+ # "alpha",
289
+ # { :participant => HashParticipant, :position => :first })
290
+ #
291
+ # or
292
+ #
293
+ # engine.register_participant("alpha", :position => :first) do
294
+ # puts "first !"
295
+ # end
296
+ #
297
+ # There are some times where you have to position a participant first
298
+ # (especially with the regex technique).
299
+ #
271
300
  # see ParticipantMap#register_participant
272
301
  #
273
302
  def register_participant (regex, participant=nil, &block)
274
303
 
275
- get_participant_map.register_participant(regex, participant, &block)
304
+ #get_participant_map.register_participant(
305
+ # regex, participant, &block)
306
+
307
+ params = if participant.class == Hash
308
+ participant
309
+ else
310
+ { :participant => participant }
311
+ end
312
+
313
+ get_participant_map.register_participant regex, params, &block
276
314
  end
277
315
 
278
316
  #
@@ -331,7 +369,7 @@ module OpenWFE
331
369
 
332
370
  freq = freq.to_s.strip
333
371
 
334
- result = if Scheduler.is_cron_string(freq)
372
+ result = if Rufus::Scheduler.is_cron_string(freq)
335
373
 
336
374
  get_scheduler.schedule(freq, listener)
337
375
  else
@@ -368,7 +406,7 @@ module OpenWFE
368
406
  #
369
407
  # TODO : implement idle_for
370
408
  #
371
- def join_until_idle ()
409
+ def join_until_idle
372
410
 
373
411
  storage = get_expression_storage
374
412
 
@@ -410,17 +448,17 @@ module OpenWFE
410
448
 
411
449
  linfo { "stop() stopping engine '#{@service_name}'" }
412
450
 
413
- @application_context.each do |name, service|
451
+ @application_context.each do |sname, service|
414
452
 
415
- next if name == self.service_name
453
+ next if sname == self.service_name
416
454
 
417
- #service.stop if service.respond_to? :stop
455
+ #if service.kind_of?(ServiceMixin)
456
+ if service.respond_to?(:stop)
418
457
 
419
- if service.kind_of? ServiceMixin
420
458
  service.stop
459
+
421
460
  linfo do
422
- "stop() stopped service '#{service.service_name}' "+
423
- "(#{service.class})"
461
+ "stop() stopped service '#{sname}' (#{service.class})"
424
462
  end
425
463
  end
426
464
  end
@@ -457,6 +495,12 @@ module OpenWFE
457
495
  te = get_expression_pool.add_observer(:error) do |c, fei, m, i, e|
458
496
  t.wakeup if (fei.parent_wfid == wfid and t.alive?)
459
497
  end
498
+ #tc = get_expression_pool.add_observer(:cancel) do |c, fe|
499
+ # if (fe.fei.wfid == wfid and fe.fei.expid == "0" and t.alive?)
500
+ # sleep 0.500
501
+ # t.wakeup
502
+ # end
503
+ #end
460
504
 
461
505
  linfo { "wait_for() #{wfid}" }
462
506
 
@@ -464,62 +508,12 @@ module OpenWFE
464
508
 
465
509
  get_expression_pool.remove_observer(to, :terminate)
466
510
  get_expression_pool.remove_observer(te, :error)
511
+ #get_expression_pool.remove_observer(tc, :cancel)
467
512
  #
468
513
  # it would work as well without specifying the channel,
469
514
  # but it's thus a little bit faster
470
515
  end
471
516
 
472
- #
473
- # Returns a hash of ProcessStatus instances. The keys of the hash
474
- # are workflow instance ids.
475
- #
476
- # A ProcessStatus is a description of the state of a process instance.
477
- # It enumerates the expressions where the process is currently
478
- # located (waiting certainly) and the errors the process currently
479
- # has (hopefully none).
480
- #
481
- def list_process_status (wfid=nil)
482
-
483
- wfid = to_wfid(wfid) if wfid
484
-
485
- result = {}
486
-
487
- get_expression_storage.real_each(wfid) do |fei, fexp|
488
- next if fexp.kind_of?(Environment)
489
- next unless fexp.apply_time
490
- (result[fei.parent_wfid] ||= ProcessStatus.new) << fexp
491
- end
492
-
493
- result.values.each do |ps|
494
- get_error_journal.get_error_log(ps.wfid).each do |error|
495
- ps << error
496
- end
497
- end
498
-
499
- class << result
500
- def to_s
501
- pretty_print_process_status(self)
502
- end
503
- end
504
-
505
- result
506
- end
507
-
508
- #
509
- # list_process_status() will be deprecated at release 1.0.0
510
- #
511
- alias :get_process_status :list_process_status
512
-
513
- #
514
- # Returns the process status of one given process instance.
515
- #
516
- def process_status (wfid)
517
-
518
- wfid = to_wfid(wfid)
519
-
520
- list_process_status(wfid).values[0]
521
- end
522
-
523
517
  #--
524
518
  # METHODS FROM THE EXPRESSION POOL
525
519
  #
@@ -535,11 +529,16 @@ module OpenWFE
535
529
  # This method returns all the expressions (the stack) a process
536
530
  # went through to reach its current state.
537
531
  #
538
- def get_process_stack (workflow_instance_id)
532
+ # If the unapplied optional parameter is set to true, all the
533
+ # expressions (even those not yet applied) that compose the process
534
+ # instance will be returned.
535
+ #
536
+ def process_stack (workflow_instance_id, unapplied=false)
539
537
 
540
- get_expression_pool.get_process_stack(workflow_instance_id)
538
+ get_expression_pool.process_stack workflow_instance_id, unapplied
541
539
  end
542
- alias :get_flow_stack :get_process_stack
540
+ alias :get_process_stack :process_stack
541
+ alias :get_flow_stack :process_stack
543
542
 
544
543
  #
545
544
  # Lists all workflow (process) instances currently in the expool (in
@@ -548,15 +547,30 @@ module OpenWFE
548
547
  # (i.e. OpenWFE::DefineExpression objects -- each representing the root
549
548
  # element of a flow).
550
549
  #
551
- # consider_subprocesses :: if true, "process-definition" expressions of
552
- # subprocesses will be returned as well.
553
- # wfid_prefix :: allows your to query for specific workflow instance
554
- # id prefixes.
555
- #
556
- def list_processes (consider_subprocesses=false, wfid_prefix=nil)
557
-
558
- get_expression_pool.list_processes(
559
- consider_subprocesses, wfid_prefix)
550
+ # :wfid ::
551
+ # will list only one process,
552
+ # <tt>:wfid => '20071208-gipijiwozo'</tt>
553
+ # :parent_wfid ::
554
+ # will list only one process, and its subprocesses,
555
+ # <tt>:parent_wfid => '20071208-gipijiwozo'</tt>
556
+ # :consider_subprocesses ::
557
+ # if true, "process-definition" expressions
558
+ # of subprocesses will be returned as well.
559
+ # :wfid_prefix ::
560
+ # allows your to query for specific workflow instance
561
+ # id prefixes. for example :
562
+ # <tt>:wfid_prefix => "200712"</tt>
563
+ # for the processes started in December.
564
+ # :wfname ::
565
+ # will return only the process instances who belongs to the given
566
+ # workflow [name].
567
+ # :wfrevision ::
568
+ # usued in conjuction with :wfname, returns only the process
569
+ # instances of a given workflow revision.
570
+ #
571
+ def list_processes (options={})
572
+
573
+ get_expression_pool.list_processes options
560
574
  end
561
575
  alias :list_workflows :list_processes
562
576
 
@@ -566,9 +580,10 @@ module OpenWFE
566
580
  #
567
581
  def cancel_process (exp_or_wfid)
568
582
 
569
- get_expression_pool.cancel_process(exp_or_wfid)
583
+ get_expression_pool.cancel_process exp_or_wfid
570
584
  end
571
585
  alias :cancel_flow :cancel_process
586
+ alias :abort_process :cancel_process
572
587
 
573
588
  #
574
589
  # Cancels the given expression (and its children if any)
@@ -579,7 +594,7 @@ module OpenWFE
579
594
  #
580
595
  def cancel_expression (exp_or_fei)
581
596
 
582
- get_expression_pool.cancel_expression(exp_or_fei)
597
+ get_expression_pool.cancel_expression exp_or_fei
583
598
  end
584
599
 
585
600
  #
@@ -588,7 +603,7 @@ module OpenWFE
588
603
  #
589
604
  def forget_expression (exp_or_fei)
590
605
 
591
- get_expression_pool.forget(exp_or_fei)
606
+ get_expression_pool.forget exp_or_fei
592
607
  end
593
608
 
594
609
  #
@@ -596,11 +611,12 @@ module OpenWFE
596
611
  #
597
612
  def pause_process (wfid)
598
613
 
599
- wfid = extract_wfid(wfid)
614
+ wfid = extract_wfid wfid
600
615
 
601
- root_expression = get_expression_pool.fetch_root(wfid)
616
+ root_expression = get_expression_pool.fetch_root wfid
602
617
 
603
- root_expression.set_variable(VAR_PAUSED, true)
618
+ get_expression_pool.paused_instances[wfid] = true
619
+ root_expression.set_variable VAR_PAUSED, true
604
620
  end
605
621
 
606
622
  #
@@ -617,7 +633,8 @@ module OpenWFE
617
633
  #
618
634
  # remove 'paused' flag
619
635
 
620
- root_expression.unset_variable(VAR_PAUSED)
636
+ get_expression_pool.paused_instances.delete wfid
637
+ root_expression.unset_variable VAR_PAUSED
621
638
 
622
639
  #
623
640
  # replay
@@ -663,18 +680,25 @@ module OpenWFE
663
680
  return get_expression_pool.fetch_engine_environment[var_name] \
664
681
  unless fei_or_wfid
665
682
 
666
- exp = if fei_or_wfid.is_a?(String)
667
-
668
- get_expression_pool.fetch_root(fei_or_wfid)
669
-
670
- else
683
+ fetch_exp(fei_or_wfid).lookup_variable var_name
684
+ end
671
685
 
672
- get_expression_pool.fetch_expression(fei_or_wfid)
673
- end
686
+ #
687
+ # Returns the variables set for a process or an expression.
688
+ #
689
+ # If a process (wfid) is given, variables of the process environment
690
+ # will be returned, else variables in the environment valid for the
691
+ # expression (fei) will be returned.
692
+ #
693
+ # If nothing (or nil) is given, the variables set in the engine
694
+ # environment will be returned.
695
+ #
696
+ def get_variables (fei_or_wfid=nil)
674
697
 
675
- raise "no expression found for '#{fei_or_wfid.to_s}'" unless exp
698
+ return get_expression_pool.fetch_engine_environment.variables \
699
+ unless fei_or_wfid
676
700
 
677
- exp.lookup_variable var_name
701
+ fetch_exp(fei_or_wfid).get_environment.variables
678
702
  end
679
703
 
680
704
  #
@@ -692,8 +716,6 @@ module OpenWFE
692
716
 
693
717
  # TODO : maybe this would be better in the ExpressionPool
694
718
 
695
- result = []
696
-
697
719
  regexp = if value
698
720
  if value.is_a?(Regexp)
699
721
  value
@@ -704,17 +726,83 @@ module OpenWFE
704
726
  nil
705
727
  end
706
728
 
707
- get_expression_storage.each_of_kind(Environment) do |fei, env|
729
+ envs = get_expression_storage.find_expressions(
730
+ :include_classes => Environment)
708
731
 
732
+ envs = envs.find_all do |env|
709
733
  val = env.variables[var_name]
734
+ (val and ((not regexp) or (regexp.match(val))))
735
+ end
736
+ envs.collect do |env|
737
+ env.fei.wfid
738
+ end
739
+
740
+ #envs.inject([]) do |r, env|
741
+ # val = env.variables[var_name]
742
+ # r << env.fei.wfid \
743
+ # if (val and ((not regexp) or (regexp.match(val))))
744
+ # r
745
+ #end
746
+ #
747
+ # seems slower...
748
+ end
749
+
750
+ #
751
+ # Use only when doing "process gardening".
752
+ #
753
+ # This method updates an expression, the 'data' parameter is expected
754
+ # to be a hash. If the expression is an Environment, the variables
755
+ # will be merged with the ones found in the data param.
756
+ # If the expression is not an Environment, the data will be merged
757
+ # into the 'applied_workitem' if any.
758
+ #
759
+ # If the merge is not possible, an exception will be raised.
760
+ #
761
+ def update_expression_data (fei, data)
762
+
763
+ fexp = fetch_exp fei
710
764
 
711
- next unless val
712
- next if regexp and (not regexp.match(val))
765
+ original = if fexp.is_a?(Environment)
766
+
767
+ fexp.variables
768
+ else
713
769
 
714
- result.push env.fei.wfid
770
+ fexp.applied_workitem.attributes
715
771
  end
716
772
 
717
- result
773
+ original.merge! data
774
+
775
+ get_expression_pool.update fexp
776
+ end
777
+
778
+ #
779
+ # A variant of update_expression() that directly replaces
780
+ # the raw representation stored within a RawExpression.
781
+ #
782
+ # Useful for modifying [not yet reached] segments of processes.
783
+ #
784
+ def update_raw_expression (fei, representation)
785
+
786
+ fexp = fetch_exp fei
787
+
788
+ raise "cannot update already applied expression" \
789
+ unless fexp.is_a?(RawExpression)
790
+
791
+ fexp.raw_representation = representation
792
+
793
+ get_expression_pool.update fexp
794
+ end
795
+
796
+ #
797
+ # Replaces an expression in the pool with a newer version of it.
798
+ #
799
+ # (useful when fixing processes on the fly)
800
+ #
801
+ def update_expression (fexp)
802
+
803
+ fexp.application_context = application_context
804
+
805
+ get_expression_pool.update fexp
718
806
  end
719
807
 
720
808
  protected
@@ -792,7 +880,11 @@ module OpenWFE
792
880
  #
793
881
  def build_scheduler
794
882
 
795
- init_service S_SCHEDULER, SchedulerService
883
+ scheduler = Rufus::Scheduler.new
884
+
885
+ @application_context[S_SCHEDULER] = scheduler
886
+
887
+ scheduler.start
796
888
  end
797
889
 
798
890
  #
@@ -821,7 +913,6 @@ module OpenWFE
821
913
 
822
914
  li = OpenWFE::LaunchItem.new
823
915
 
824
- #if launch_object[0, 1] == '<' or launch_object.match("\n")
825
916
  if launch_object[0, 1] == '<' or launch_object.index("\n")
826
917
 
827
918
  li.workflow_definition_url = "field:__definition"
@@ -836,164 +927,24 @@ module OpenWFE
836
927
  end
837
928
  end
838
929
 
839
- end
840
-
841
- #
842
- # ProcessStatus represents information about the status of a workflow
843
- # process instance.
844
- #
845
- # The status is mainly a list of expressions and a hash of errors.
846
- #
847
- # Instances of this class are obtained via Engine.process_status().
848
- #
849
- class ProcessStatus
850
-
851
- #
852
- # the String workflow instance id of the Process.
853
- #
854
- attr_reader :wfid
855
-
856
- #
857
- # The list of the expressions currently active in the process instance.
858
- #
859
- # For instance, if your process definition is currently in a
860
- # concurrence, more than one expressions may be listed here.
861
- #
862
- attr_reader :expressions
863
-
864
- #
865
- # A hash whose values are ProcessError instances, the keys
866
- # are FlowExpressionId instances (fei) (identifying the expressions
867
- # that are concerned with the error)
868
- #
869
- attr_reader :errors
870
-
871
- #
872
- # The time at which the process got launched.
873
- #
874
- attr_reader :launch_time
875
-
876
- def initialize
877
- @wfid = nil
878
- @expressions = []
879
- @errors = {}
880
- @launch_time = nil
881
- end
882
-
883
- #
884
- # Returns true if the process is in pause.
885
- #
886
- def paused?
887
-
888
- exp = @expressions[0]
889
- exp != nil and exp.paused?
890
- end
891
-
892
- #
893
- # this method is used by Engine.get_process_status() when
894
- # it prepares its results.
895
- #
896
- def << (item)
897
-
898
- if item.kind_of?(FlowExpression)
899
- add_expression item
900
- else
901
- add_error item
902
- end
903
- end
904
-
905
- #
906
- # A String representation, handy for debugging, quick viewing.
907
- #
908
- def to_s
909
- s = ""
910
- s << "-- #{self.class.name} --\n"
911
- s << " wfid : #{@wfid}\n"
912
- s << " expressions :\n"
913
- @expressions.each do |fexp|
914
- s << " #{fexp.fei}\n"
915
- end
916
- s << " errors : #{@errors.size}\n"
917
- s << " paused : #{paused?}"
918
- s
919
- end
920
-
921
- protected
922
-
923
- def add_expression (fexp)
930
+ #
931
+ # In case of wfid, returns the root expression of the process,
932
+ # in case of fei, returns the expression itself.
933
+ #
934
+ def fetch_exp (fei_or_wfid)
924
935
 
925
- set_wfid fexp.fei.parent_wfid
936
+ exp = if fei_or_wfid.is_a?(String)
926
937
 
927
- @launch_time = fexp.apply_time if fexp.fei.expid == '0'
938
+ get_expression_pool.fetch_root fei_or_wfid
928
939
 
929
- exps = @expressions
930
- @expressions = []
940
+ else
931
941
 
932
- added = false
933
- @expressions = exps.collect do |fe|
934
- if added or fe.fei.wfid != fexp.fei.wfid
935
- fe
936
- else
937
- if OpenWFE::starts_with(fexp.fei.expid, fe.fei.expid)
938
- added = true
939
- fexp
940
- elsif OpenWFE::starts_with(fe.fei.expid, fexp.fei.expid)
941
- added = true
942
- fe
943
- else
944
- fe
945
- end
946
- end
942
+ get_expression_pool.fetch_expression fei_or_wfid
947
943
  end
948
- @expressions << fexp unless added
949
- end
950
-
951
- def add_error (error)
952
- @errors[error.fei] = error
953
- end
954
-
955
- def set_wfid (wfid)
956
944
 
957
- return if @wfid
958
- @wfid = wfid
945
+ exp or raise "no expression found for '#{fei_or_wfid.to_s}'"
959
946
  end
960
947
  end
961
948
 
962
- #
963
- # Renders a nice, terminal oriented, representation of an
964
- # Engine.get_process_status() result.
965
- #
966
- # You usually directly benefit from this when doing
967
- #
968
- # puts engine.get_process_status.to_s
969
- #
970
- def pretty_print_process_status (ps)
971
-
972
- s = ""
973
- s << "process_id | name | rev | brn | err | paused? \n"
974
- s << "--------------------+-------------------+---------+-----+-----+---------\n"
975
-
976
- ps.keys.sort.each do |wfid|
977
-
978
- status = ps[wfid]
979
- fexp = status.expressions[0]
980
- ffei = fexp.fei
981
-
982
- s << "%-19s" % wfid[0, 19]
983
- s << " | "
984
- s << "%-17s" % ffei.workflow_definition_name[0, 17]
985
- s << " | "
986
- s << "%-7s" % ffei.workflow_definition_revision[0, 7]
987
- s << " | "
988
- s << "%3s" % status.expressions.size.to_s[0, 3]
989
- s << " | "
990
- s << "%3s" % status.errors.size.to_s[0, 3]
991
- s << " | "
992
- s << "%5s" % status.paused?.to_s
993
- s << "\n"
994
- end
995
- s
996
- end
997
-
998
949
  end
999
950