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