openwferu 0.9.16 → 0.9.17

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