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.
- data/examples/bigflow.rb +19 -0
- data/examples/csv_weather.rb +23 -0
- data/examples/engine_template.rb +7 -0
- data/lib/openwfe/contextual.rb +0 -2
- data/lib/openwfe/engine/engine.rb +137 -34
- data/lib/openwfe/engine/file_persisted_engine.rb +0 -5
- data/lib/openwfe/exceptions.rb +0 -2
- data/lib/openwfe/expool/errorjournal.rb +83 -7
- data/lib/openwfe/expool/expressionpool.rb +279 -60
- data/lib/openwfe/expool/expstorage.rb +7 -6
- data/lib/openwfe/expool/yamlexpstorage.rb +17 -14
- data/lib/openwfe/expressions/condition.rb +10 -7
- data/lib/openwfe/expressions/environment.rb +11 -1
- data/lib/openwfe/expressions/fe_command.rb +14 -1
- data/lib/openwfe/expressions/fe_cron.rb +29 -14
- data/lib/openwfe/expressions/fe_define.rb +26 -1
- data/lib/openwfe/expressions/fe_iterator.rb +2 -0
- data/lib/openwfe/expressions/fe_losfor.rb +20 -15
- data/lib/openwfe/expressions/fe_misc.rb +0 -2
- data/lib/openwfe/expressions/fe_participant.rb +78 -24
- data/lib/openwfe/expressions/fe_reserve.rb +0 -2
- data/lib/openwfe/expressions/fe_sleep.rb +0 -4
- data/lib/openwfe/expressions/fe_subprocess.rb +34 -0
- data/lib/openwfe/expressions/fe_value.rb +46 -4
- data/lib/openwfe/expressions/fe_wait.rb +0 -2
- data/lib/openwfe/expressions/flowexpression.rb +39 -9
- data/lib/openwfe/expressions/raw.rb +73 -48
- data/lib/openwfe/expressions/raw_prog.rb +45 -15
- data/lib/openwfe/expressions/simplerep.rb +54 -7
- data/lib/openwfe/expressions/time.rb +5 -2
- data/lib/openwfe/expressions/timeout.rb +0 -2
- data/lib/openwfe/flowexpressionid.rb +26 -2
- data/lib/openwfe/participants/enoparticipants.rb +6 -1
- data/lib/openwfe/participants/participant.rb +0 -2
- data/lib/openwfe/participants/participantmap.rb +21 -7
- data/lib/openwfe/participants/participants.rb +29 -0
- data/lib/openwfe/rest/exception.rb +0 -2
- data/lib/openwfe/storage/yamlfilestorage.rb +4 -1
- data/lib/openwfe/util/dollar.rb +0 -2
- data/lib/openwfe/util/lru.rb +0 -2
- data/lib/openwfe/util/observable.rb +1 -1
- data/lib/openwfe/util/scheduler.rb +4 -4
- data/lib/openwfe/util/schedulers.rb +0 -2
- data/lib/openwfe/util/workqueue.rb +34 -91
- data/lib/openwfe/utils.rb +35 -28
- data/lib/openwfe/version.rb +1 -1
- data/lib/openwfe/workitem.rb +1 -1
- data/test/clone_test.rb +51 -0
- data/test/concurrence_test.rb +78 -0
- data/test/cron_test_2.rb +50 -0
- data/test/flowtestbase.rb +40 -12
- data/test/ft_21_cron.rb +32 -6
- data/test/ft_26_load.rb +8 -2
- data/test/ft_26c_load.rb +19 -0
- data/test/ft_27_getflowpos.rb +4 -4
- data/test/ft_2_concurrence.rb +14 -9
- data/test/ft_32_journal.rb +1 -1
- data/test/ft_32c_journal.rb +3 -2
- data/test/ft_32d_journal.rb +2 -1
- data/test/ft_34_cancelwfid.rb +7 -3
- data/test/ft_35_localdefs.rb +13 -0
- data/test/ft_38_tag.rb +8 -6
- data/test/ft_49_condition.rb +7 -1
- data/test/ft_55_ptimeout.rb +13 -14
- data/test/ft_57_a.rb +17 -0
- data/test/ft_58_ejournal.rb +3 -3
- data/test/ft_59_ps.rb +6 -6
- data/test/ft_60_ecancel.rb +3 -5
- data/test/ft_61_elsub.rb +2 -4
- data/test/ft_63_pause.rb +122 -0
- data/test/ft_64_alias.rb +102 -0
- data/test/ft_64_clone.rb +69 -0
- data/test/ft_65_stringlaunch.rb +61 -0
- data/test/ft_66_subforget.rb +70 -0
- data/test/ft_67_schedlaunch.rb +102 -0
- data/test/ft_68_ifparticipant.rb +70 -0
- data/test/ft_69_cancelmissing.rb +49 -0
- data/test/ft_6_lambda.rb +23 -3
- data/test/ft_70_lookupvar.rb +55 -0
- data/test/ft_7_lose.rb +1 -1
- data/test/ft_tests.rb +10 -1
- data/test/hparticipant_test.rb +6 -6
- data/test/param_test.rb +1 -1
- data/test/{rake_test.rb → rake_ltest.rb} +9 -2
- data/test/rake_qtest.rb +3 -1
- data/test/raw_prog_test.rb +11 -3
- data/test/restart_sleep_test.rb +44 -6
- data/test/ruby_procdef_test.rb +129 -0
- data/test/rutest_utils.rb +1 -0
- data/test/sec_test.rb +3 -3
- metadata +19 -4
data/examples/bigflow.rb
ADDED
@@ -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
|
+
|
data/examples/engine_template.rb
CHANGED
@@ -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
|
#
|
data/lib/openwfe/contextual.rb
CHANGED
@@ -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
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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
|
-
|
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,
|
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
|
-
|
433
|
+
linfo { "wait_for() #{wfid}" }
|
432
434
|
|
433
435
|
t.join
|
434
436
|
|
435
|
-
get_expression_pool.remove_observer
|
436
|
-
get_expression_pool.remove_observer
|
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
|
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
|
-
#
|
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 << "
|
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,
|
data/lib/openwfe/exceptions.rb
CHANGED
@@ -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 :
|
107
|
-
s << " fei :
|
108
|
-
s << " message :
|
109
|
-
s << " workitem :
|
110
|
-
s << "
|
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
|
-
|
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.
|