openwferu 0.9.13 → 0.9.14

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 (91) hide show
  1. data/examples/bigflow.rb +19 -0
  2. data/examples/csv_weather.rb +23 -0
  3. data/examples/engine_template.rb +7 -0
  4. data/lib/openwfe/contextual.rb +0 -2
  5. data/lib/openwfe/engine/engine.rb +137 -34
  6. data/lib/openwfe/engine/file_persisted_engine.rb +0 -5
  7. data/lib/openwfe/exceptions.rb +0 -2
  8. data/lib/openwfe/expool/errorjournal.rb +83 -7
  9. data/lib/openwfe/expool/expressionpool.rb +279 -60
  10. data/lib/openwfe/expool/expstorage.rb +7 -6
  11. data/lib/openwfe/expool/yamlexpstorage.rb +17 -14
  12. data/lib/openwfe/expressions/condition.rb +10 -7
  13. data/lib/openwfe/expressions/environment.rb +11 -1
  14. data/lib/openwfe/expressions/fe_command.rb +14 -1
  15. data/lib/openwfe/expressions/fe_cron.rb +29 -14
  16. data/lib/openwfe/expressions/fe_define.rb +26 -1
  17. data/lib/openwfe/expressions/fe_iterator.rb +2 -0
  18. data/lib/openwfe/expressions/fe_losfor.rb +20 -15
  19. data/lib/openwfe/expressions/fe_misc.rb +0 -2
  20. data/lib/openwfe/expressions/fe_participant.rb +78 -24
  21. data/lib/openwfe/expressions/fe_reserve.rb +0 -2
  22. data/lib/openwfe/expressions/fe_sleep.rb +0 -4
  23. data/lib/openwfe/expressions/fe_subprocess.rb +34 -0
  24. data/lib/openwfe/expressions/fe_value.rb +46 -4
  25. data/lib/openwfe/expressions/fe_wait.rb +0 -2
  26. data/lib/openwfe/expressions/flowexpression.rb +39 -9
  27. data/lib/openwfe/expressions/raw.rb +73 -48
  28. data/lib/openwfe/expressions/raw_prog.rb +45 -15
  29. data/lib/openwfe/expressions/simplerep.rb +54 -7
  30. data/lib/openwfe/expressions/time.rb +5 -2
  31. data/lib/openwfe/expressions/timeout.rb +0 -2
  32. data/lib/openwfe/flowexpressionid.rb +26 -2
  33. data/lib/openwfe/participants/enoparticipants.rb +6 -1
  34. data/lib/openwfe/participants/participant.rb +0 -2
  35. data/lib/openwfe/participants/participantmap.rb +21 -7
  36. data/lib/openwfe/participants/participants.rb +29 -0
  37. data/lib/openwfe/rest/exception.rb +0 -2
  38. data/lib/openwfe/storage/yamlfilestorage.rb +4 -1
  39. data/lib/openwfe/util/dollar.rb +0 -2
  40. data/lib/openwfe/util/lru.rb +0 -2
  41. data/lib/openwfe/util/observable.rb +1 -1
  42. data/lib/openwfe/util/scheduler.rb +4 -4
  43. data/lib/openwfe/util/schedulers.rb +0 -2
  44. data/lib/openwfe/util/workqueue.rb +34 -91
  45. data/lib/openwfe/utils.rb +35 -28
  46. data/lib/openwfe/version.rb +1 -1
  47. data/lib/openwfe/workitem.rb +1 -1
  48. data/test/clone_test.rb +51 -0
  49. data/test/concurrence_test.rb +78 -0
  50. data/test/cron_test_2.rb +50 -0
  51. data/test/flowtestbase.rb +40 -12
  52. data/test/ft_21_cron.rb +32 -6
  53. data/test/ft_26_load.rb +8 -2
  54. data/test/ft_26c_load.rb +19 -0
  55. data/test/ft_27_getflowpos.rb +4 -4
  56. data/test/ft_2_concurrence.rb +14 -9
  57. data/test/ft_32_journal.rb +1 -1
  58. data/test/ft_32c_journal.rb +3 -2
  59. data/test/ft_32d_journal.rb +2 -1
  60. data/test/ft_34_cancelwfid.rb +7 -3
  61. data/test/ft_35_localdefs.rb +13 -0
  62. data/test/ft_38_tag.rb +8 -6
  63. data/test/ft_49_condition.rb +7 -1
  64. data/test/ft_55_ptimeout.rb +13 -14
  65. data/test/ft_57_a.rb +17 -0
  66. data/test/ft_58_ejournal.rb +3 -3
  67. data/test/ft_59_ps.rb +6 -6
  68. data/test/ft_60_ecancel.rb +3 -5
  69. data/test/ft_61_elsub.rb +2 -4
  70. data/test/ft_63_pause.rb +122 -0
  71. data/test/ft_64_alias.rb +102 -0
  72. data/test/ft_64_clone.rb +69 -0
  73. data/test/ft_65_stringlaunch.rb +61 -0
  74. data/test/ft_66_subforget.rb +70 -0
  75. data/test/ft_67_schedlaunch.rb +102 -0
  76. data/test/ft_68_ifparticipant.rb +70 -0
  77. data/test/ft_69_cancelmissing.rb +49 -0
  78. data/test/ft_6_lambda.rb +23 -3
  79. data/test/ft_70_lookupvar.rb +55 -0
  80. data/test/ft_7_lose.rb +1 -1
  81. data/test/ft_tests.rb +10 -1
  82. data/test/hparticipant_test.rb +6 -6
  83. data/test/param_test.rb +1 -1
  84. data/test/{rake_test.rb → rake_ltest.rb} +9 -2
  85. data/test/rake_qtest.rb +3 -1
  86. data/test/raw_prog_test.rb +11 -3
  87. data/test/restart_sleep_test.rb +44 -6
  88. data/test/ruby_procdef_test.rb +129 -0
  89. data/test/rutest_utils.rb +1 -0
  90. data/test/sec_test.rb +3 -3
  91. metadata +19 -4
@@ -0,0 +1,19 @@
1
+ #
2
+ # just a sample
3
+ #
4
+
5
+ class BigFlow0 < OpenWFE::ProcessDefinition
6
+
7
+ sequence do
8
+ alpha
9
+ concurrence do
10
+ bravo
11
+ cursor do
12
+ alpha
13
+ bravo
14
+ end
15
+ alpha :activity => "brush teeth"
16
+ end
17
+ bravo
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require 'rubygems'
3
+ require 'openwfe/extras/util/csvtable'
4
+
5
+ include OpenWFE::Extras
6
+
7
+ $table = CsvTable.new("http://spreadsheets.google.com/pub?key=pCkopoeZwCNsMWOVeDjR1TQ&output=csv&gid=0")
8
+
9
+ def decide (hash)
10
+
11
+ $table.transform hash
12
+
13
+ puts " weather : #{hash['weather']}, month : #{hash['month']}"
14
+ puts " => take umbrella ? #{hash['take_umbrella?']}"
15
+ puts
16
+ end
17
+
18
+ puts
19
+
20
+ decide({ "weather" => "raining", "month" => "december" })
21
+ decide({ "weather" => "sunny", "month" => "december" })
22
+ decide({ "weather" => "cloudy", "month" => "may" })
23
+
@@ -201,6 +201,13 @@ end
201
201
  # the workitem to it over TCP
202
202
 
203
203
 
204
+ engine.reschedule
205
+ #
206
+ # this method has to be called after all the participants have been
207
+ # added, it looks for temporal expressions (sleep, cron, ...) to
208
+ # reschedule.
209
+
210
+
204
211
  #
205
212
  # === joining the engine's scheduler thread
206
213
  #
@@ -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
  # "made in Japan"
@@ -143,6 +143,7 @@ module OpenWFE
143
143
  # have been added.
144
144
  #
145
145
  def reschedule
146
+
146
147
  get_expression_pool.reschedule()
147
148
  end
148
149
 
@@ -158,6 +159,7 @@ module OpenWFE
158
159
  # This method can be useful in some scenarii though.
159
160
  #
160
161
  def pre_launch_check (launchitem)
162
+
161
163
  get_expression_pool.prepare_raw_expression(launchitem)
162
164
  end
163
165
 
@@ -174,31 +176,28 @@ module OpenWFE
174
176
  # Returns the FlowExpressionId instance of the expression at the
175
177
  # root of the newly launched process.
176
178
  #
177
- def launch (launch_object)
178
-
179
- launchitem = if launch_object.kind_of?(OpenWFE::LaunchItem)
180
-
181
- launch_object
182
-
183
- elsif launch_object.kind_of?(Class)
184
-
185
- LaunchItem.new launch_object
186
-
187
- elsif launch_object.kind_of? String
188
-
189
- li = OpenWFE::LaunchItem.new
190
-
191
- if launch_object[0, 1] == '<'
192
- li.workflowDefinitionUrl = "field:__definition"
193
- li['definition'] = launch_object
194
- else
195
- li.workflowDefinitionUrl = launch_object
196
- end
179
+ # Options for scheduled launches like :at, :in and :cron are accepted
180
+ # via the 'options' optional parameter.
181
+ # For example :
182
+ #
183
+ # engine.launch(launch_item)
184
+ # # will launch immediately
185
+ #
186
+ # engine.launch(launch_item, :in => "1d20m")
187
+ # # will launch in one day and twenty minutes
188
+ #
189
+ # engine.launch(launch_item, :at => "Tue Sep 11 20:23:02 +0900 2007")
190
+ # # will launch at that point in time
191
+ #
192
+ # engine.launch(launch_item, :cron => "0 5 * * *")
193
+ # # will launch that same process every day,
194
+ # # five minutes after midnight (see "man 5 crontab")
195
+ #
196
+ def launch (launch_object, options={})
197
197
 
198
- li
199
- end
198
+ launchitem = extract_launchitem launch_object
200
199
 
201
- fei = get_expression_pool.launch launchitem
200
+ fei = get_expression_pool.launch launchitem, options
202
201
 
203
202
  fei.dup
204
203
  #
@@ -231,6 +230,9 @@ module OpenWFE
231
230
  end
232
231
  end
233
232
 
233
+ alias :forward :reply
234
+ alias :proceed :reply
235
+
234
236
  #
235
237
  # Registers a participant in this [embedded] engine.
236
238
  # This method is a shortcut to the ParticipantMap method
@@ -422,18 +424,18 @@ module OpenWFE
422
424
  t = Thread.new { Thread.stop }
423
425
 
424
426
  to = get_expression_pool.add_observer(:terminate) do |c, fe, wi|
425
- t.wakeup if fe.fei.workflow_instance_id == wfid
427
+ t.wakeup if (fe.fei.workflow_instance_id == wfid and t.alive?)
426
428
  end
427
- te = get_expression_pool.add_observer(:error) do |c, fei, m, wi, se|
428
- t.wakeup if fei.parent_wfid == wfid
429
+ te = get_expression_pool.add_observer(:error) do |c, fei, m, i, e|
430
+ t.wakeup if (fei.parent_wfid == wfid and t.alive?)
429
431
  end
430
432
 
431
- ldebug { "wait_for() #{wfid}" }
433
+ linfo { "wait_for() #{wfid}" }
432
434
 
433
435
  t.join
434
436
 
435
- get_expression_pool.remove_observer to, :terminate
436
- get_expression_pool.remove_observer te, :error
437
+ get_expression_pool.remove_observer(to, :terminate)
438
+ get_expression_pool.remove_observer(te, :error)
437
439
  #
438
440
  # it would work as well without specifying the channel,
439
441
  # but it's thus a little bit faster
@@ -448,7 +450,7 @@ module OpenWFE
448
450
  # located (waiting certainly) and the errors the process currently
449
451
  # has (hopefully none).
450
452
  #
451
- def get_process_status (wfid=nil)
453
+ def list_process_status (wfid=nil)
452
454
 
453
455
  wfid = to_wfid(wfid) if wfid
454
456
 
@@ -475,6 +477,21 @@ module OpenWFE
475
477
  result
476
478
  end
477
479
 
480
+ #
481
+ # list_process_status() will be deprecated at release 1.0.0
482
+ #
483
+ alias :get_process_status :list_process_status
484
+
485
+ #
486
+ # Returns the process status of one given process instance.
487
+ #
488
+ def process_status (wfid)
489
+
490
+ wfid = to_wfid(wfid)
491
+
492
+ list_process_status(wfid).values[0]
493
+ end
494
+
478
495
  #--
479
496
  # METHODS FROM THE EXPRESSION POOL
480
497
  #
@@ -546,6 +563,48 @@ module OpenWFE
546
563
  get_expression_pool.forget(exp_or_fei)
547
564
  end
548
565
 
566
+ #
567
+ # Pauses a process (sets its /__paused__ variable to true).
568
+ #
569
+ def pause_process (wfid)
570
+
571
+ get_expression_pool.pause_process(wfid)
572
+ end
573
+
574
+ #
575
+ # Restarts a process : removes its 'paused' flag (variable) and makes
576
+ # sure to 'replay' events (replies) that came for it while it was
577
+ # in pause.
578
+ #
579
+ def resume_process (wfid)
580
+
581
+ get_expression_pool.resume_process(wfid)
582
+ end
583
+
584
+ #
585
+ # Looks up a process variable in a process.
586
+ # If fei_or_wfid is not given, will simply look in the
587
+ # 'engine environment' (where the top level variables '//' do reside).
588
+ #
589
+ def lookup_variable (var_name, fei_or_wfid=nil)
590
+
591
+ return get_expression_pool.fetch_engine_environment[var_name] \
592
+ unless fei_or_wfid
593
+
594
+ exp = if fei_or_wfid.is_a?(String)
595
+
596
+ get_expression_pool.fetch_root(fei_or_wfid)
597
+
598
+ else
599
+
600
+ get_expression_pool.fetch_expression(fei_or_wfid)
601
+ end
602
+
603
+ raise "no expression found for '#{fei_or_wfid.to_s}'" unless exp
604
+
605
+ exp.lookup_variable var_name
606
+ end
607
+
549
608
  protected
550
609
 
551
610
  #--
@@ -633,6 +692,38 @@ module OpenWFE
633
692
  init_service(S_ERROR_JOURNAL, InMemoryErrorJournal)
634
693
  end
635
694
 
695
+ #
696
+ # Turns the raw launch request info into a LaunchItem instance.
697
+ #
698
+ def extract_launchitem (launch_object)
699
+
700
+ if launch_object.kind_of?(OpenWFE::LaunchItem)
701
+
702
+ launch_object
703
+
704
+ elsif launch_object.kind_of?(Class)
705
+
706
+ LaunchItem.new launch_object
707
+
708
+ elsif launch_object.kind_of?(String)
709
+
710
+ li = OpenWFE::LaunchItem.new
711
+
712
+ #if launch_object[0, 1] == '<' or launch_object.match("\n")
713
+ if launch_object[0, 1] == '<' or launch_object.index("\n")
714
+
715
+ li.workflow_definition_url = "field:__definition"
716
+ li['__definition'] = launch_object
717
+
718
+ else
719
+
720
+ li.workflow_definition_url = launch_object
721
+ end
722
+
723
+ li
724
+ end
725
+ end
726
+
636
727
  end
637
728
 
638
729
  #
@@ -659,7 +750,7 @@ module OpenWFE
659
750
  attr_reader :expressions
660
751
 
661
752
  #
662
- # a hash whose values are ProcessError instances, the keys
753
+ # A hash whose values are ProcessError instances, the keys
663
754
  # are FlowExpressionId instances (fei) (identifying the expressions
664
755
  # that are concerned with the error)
665
756
  #
@@ -671,6 +762,15 @@ module OpenWFE
671
762
  @errors = {}
672
763
  end
673
764
 
765
+ #
766
+ # Returns true if the process is in pause.
767
+ #
768
+ def paused?
769
+
770
+ exp = @expressions[0]
771
+ exp != nil and exp.paused?
772
+ end
773
+
674
774
  #
675
775
  # this method is used by Engine.get_process_status() when
676
776
  # it prepares its results.
@@ -695,7 +795,8 @@ module OpenWFE
695
795
  @expressions.each do |fexp|
696
796
  s << " #{fexp.fei}\n"
697
797
  end
698
- s << " errors : #{@errors.size}"
798
+ s << " errors : #{@errors.size}\n"
799
+ s << " paused : #{paused?}"
699
800
  s
700
801
  end
701
802
 
@@ -751,8 +852,8 @@ module OpenWFE
751
852
  def pretty_print_process_status (ps)
752
853
 
753
854
  s = ""
754
- s << "process_id | name | rev | brn | err\n"
755
- s << "--------------------+-------------------+---------+-----+-----\n"
855
+ s << "process_id | name | rev | brn | err | paused? \n"
856
+ s << "--------------------+-------------------+---------+-----+-----+---------\n"
756
857
 
757
858
  ps.keys.sort.each do |wfid|
758
859
 
@@ -769,6 +870,8 @@ module OpenWFE
769
870
  s << "%3s" % status.expressions.size.to_s[0, 3]
770
871
  s << " | "
771
872
  s << "%3s" % status.errors.size.to_s[0, 3]
873
+ s << " | "
874
+ s << "%5s" % status.paused?.to_s
772
875
  s << "\n"
773
876
  end
774
877
  s
@@ -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
  # "made in Japan"
@@ -64,8 +62,6 @@ module OpenWFE
64
62
  #
65
63
  def build_expression_storage ()
66
64
 
67
- @application_context[:work_directory] = "./work"
68
-
69
65
  init_service(S_EXPRESSION_STORAGE, YamlFileExpressionStorage)
70
66
  end
71
67
 
@@ -93,7 +89,6 @@ module OpenWFE
93
89
  def build_expression_storage ()
94
90
 
95
91
  @application_context[:expression_cache_size] = 1000
96
- @application_context[:work_directory] = "./work"
97
92
 
98
93
  init_service(
99
94
  S_EXPRESSION_STORAGE,
@@ -30,8 +30,6 @@
30
30
  # POSSIBILITY OF SUCH DAMAGE.
31
31
  #++
32
32
  #
33
- # $Id: workitem.rb 3555 2006-11-13 00:47:53Z jmettraux $
34
- #
35
33
 
36
34
  #
37
35
  # Made in Japan
@@ -80,10 +80,15 @@ module OpenWFE
80
80
  #
81
81
  attr_reader :stacktrace
82
82
 
83
+ #
84
+ # The error class (String) of the top level error
85
+ #
86
+ attr_reader :error_class
87
+
83
88
  def initialize (*args)
84
89
 
85
90
  @date = Time.new
86
- @fei, @message, @workitem, @stacktrace = args
91
+ @fei, @message, @workitem, @error_class, @stacktrace = args
87
92
  end
88
93
 
89
94
  #
@@ -103,13 +108,34 @@ module OpenWFE
103
108
  def to_s
104
109
  s = ""
105
110
  s << "-- #{self.class.name} --\n"
106
- s << " date : #{@date}\n"
107
- s << " fei : #{@fei}\n"
108
- s << " message : #{@message}\n"
109
- s << " workitem : ...\n"
110
- s << " stacktrace : #{@stacktrace[0, 80]}\n"
111
+ s << " date : #{@date}\n"
112
+ s << " fei : #{@fei}\n"
113
+ s << " message : #{@message}\n"
114
+ s << " workitem : ...\n"
115
+ s << " error_class : #{@error_class}\n"
116
+ s << " stacktrace : #{@stacktrace[0, 80]}\n"
111
117
  s
112
118
  end
119
+
120
+ #
121
+ # Returns a hash
122
+ #
123
+ def hash
124
+ to_s.hash
125
+ #
126
+ # a bit costly but as it's only used by resume_process()...
127
+ end
128
+
129
+ #
130
+ # Returns true if the other instance is a ProcessError and is the
131
+ # same error as this one.
132
+ #
133
+ def == (other)
134
+ return false unless other.is_a?(ProcessError)
135
+ return to_s == other.to_s
136
+ #
137
+ # a bit costly but as it's only used by resume_process()...
138
+ end
113
139
  end
114
140
 
115
141
  #
@@ -129,7 +155,13 @@ module OpenWFE
129
155
  #
130
156
  # logs each error occuring in the expression pool
131
157
 
132
- record_error(ProcessError.new(*args))
158
+ begin
159
+
160
+ record_error(ProcessError.new(*args))
161
+
162
+ rescue Exception => e
163
+ lwarn { "*** process error : \n" + args.join("\n") }
164
+ end
133
165
  end
134
166
  end
135
167
 
@@ -241,6 +273,18 @@ module OpenWFE
241
273
  @per_processes.delete(wfid)
242
274
  end
243
275
 
276
+ #
277
+ # Removes a list of errors from the error journal.
278
+ #
279
+ def remove_errors (wfid, errors)
280
+
281
+ log = get_error_log wfid
282
+
283
+ errors.each do |e|
284
+ log.delete e
285
+ end
286
+ end
287
+
244
288
  #
245
289
  # Reads all the error logs currently stored.
246
290
  # Returns a hash wfid --> error list.
@@ -332,6 +376,38 @@ module OpenWFE
332
376
  File.delete(get_path(wfid))
333
377
  end
334
378
 
379
+ #
380
+ # Removes a list of errors from this error journal.
381
+ #
382
+ def remove_errors (wfid, errors)
383
+
384
+ # load all errors
385
+
386
+ log = get_error_log wfid
387
+
388
+ # remove the given errors
389
+
390
+ errors.each do |e|
391
+ log.delete e
392
+ end
393
+
394
+ # rewrite error file
395
+
396
+ path = get_path wfid
397
+
398
+ if log.size > 0
399
+
400
+ File.open(path, "w") do |f|
401
+ log.each do |e|
402
+ f.puts e.to_yaml
403
+ end
404
+ end
405
+ else
406
+
407
+ File.delete path
408
+ end
409
+ end
410
+
335
411
  #
336
412
  # Reads all the error logs currently stored.
337
413
  # Returns a hash wfid --> error list.