openwferu 0.9.2 → 0.9.3
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/mano_tracker.rb +165 -0
- data/examples/scheduler_cron_usage.rb +46 -0
- data/examples/scheduler_usage.rb +54 -0
- data/lib/openwfe/contextual.rb +7 -1
- data/lib/openwfe/engine/engine.rb +58 -15
- data/lib/openwfe/expool/expressionpool.rb +116 -14
- data/lib/openwfe/expool/expstorage.rb +12 -12
- data/lib/openwfe/expool/journalexpstorage.rb +1 -1
- data/lib/openwfe/expool/yamlexpstorage.rb +58 -22
- data/lib/openwfe/expressions/environment.rb +32 -2
- data/lib/openwfe/expressions/expressionmap.rb +17 -0
- data/lib/openwfe/expressions/fe_condition.rb +122 -0
- data/lib/openwfe/expressions/fe_cursor.rb +14 -5
- data/lib/openwfe/expressions/fe_participant.rb +55 -4
- data/lib/openwfe/expressions/fe_raw.rb +43 -12
- data/lib/openwfe/expressions/fe_subprocess.rb +10 -0
- data/lib/openwfe/expressions/fe_time.rb +117 -22
- data/lib/openwfe/expressions/fe_value.rb +27 -8
- data/lib/openwfe/expressions/flowexpression.rb +13 -6
- data/lib/openwfe/expressions/raw_prog.rb +13 -11
- data/lib/openwfe/expressions/timeout.rb +94 -0
- data/lib/openwfe/flowexpressionid.rb +17 -19
- data/lib/openwfe/logging.rb +35 -16
- data/lib/openwfe/participants/atomparticipants.rb +31 -7
- data/lib/openwfe/participants/enoparticipant.rb +43 -3
- data/lib/openwfe/participants/participant.rb +21 -1
- data/lib/openwfe/participants/participantmap.rb +4 -2
- data/lib/openwfe/participants/participants.rb +12 -17
- data/lib/openwfe/participants/soapparticipants.rb +15 -3
- data/lib/openwfe/rudefinitions.rb +3 -0
- data/lib/openwfe/service.rb +8 -0
- data/lib/openwfe/storage/yamlfilestorage.rb +85 -47
- data/lib/openwfe/{otime.rb → util/otime.rb} +0 -0
- data/lib/openwfe/util/scheduler.rb +415 -231
- data/lib/openwfe/util/schedulers.rb +11 -3
- data/lib/openwfe/util/stoppable.rb +69 -0
- data/lib/openwfe/utils.rb +14 -25
- data/lib/openwfe/workitem.rb +12 -6
- data/lib/openwfe/worklist/storeparticipant.rb +145 -0
- data/test/{atomtest.rb → atom_test.rb} +0 -0
- data/test/{crontest.rb → cron_test.rb} +7 -6
- data/test/cronline_test.rb +51 -0
- data/test/{dollartest.rb → dollar_test.rb} +0 -0
- data/test/{feitest.rb → fei_test.rb} +0 -0
- data/test/file_persistence_test.rb +15 -9
- data/test/flowtestbase.rb +11 -5
- data/test/ft_0.rb +8 -0
- data/test/ft_10_loop.rb +72 -10
- data/test/ft_11_ppd.rb +49 -0
- data/test/ft_17_condition.rb +83 -0
- data/test/ft_18_pname.rb +59 -0
- data/test/hparticipant_test.rb +96 -0
- data/test/{misctest.rb → misc_test.rb} +1 -1
- data/test/rake_qtest.rb +10 -4
- data/test/rake_test.rb +12 -1
- data/test/raw_prog_test.rb +1 -1
- data/test/restart_cron_test.rb +78 -0
- data/test/restart_test.rb +79 -0
- data/test/scheduler_test.rb +92 -0
- data/test/{timetest.rb → time_test.rb} +3 -38
- data/test/timeout_test.rb +73 -0
- metadata +26 -11
- data/lib/openwfe/worklist/worklists.rb +0 -175
@@ -0,0 +1,165 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2007, John Mettraux OpenWFE.org
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# . Redistributions of source code must retain the above copyright notice, this
|
10
|
+
# list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# . Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
14
|
+
# and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# . Neither the name of the "OpenWFE" nor the names of its contributors may be
|
17
|
+
# used to endorse or promote products derived from this software without
|
18
|
+
# specific prior written permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
#++
|
32
|
+
#
|
33
|
+
# $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
|
34
|
+
#
|
35
|
+
|
36
|
+
#
|
37
|
+
# "made in Japan"
|
38
|
+
#
|
39
|
+
# John Mettraux at openwfe.org
|
40
|
+
#
|
41
|
+
|
42
|
+
#
|
43
|
+
# see
|
44
|
+
# http://groups.google.com/group/openwferu-users/browse_frm/thread/81294030fc52cd04
|
45
|
+
# for the context of this example
|
46
|
+
#
|
47
|
+
|
48
|
+
require 'openwfe/engine/engine'
|
49
|
+
require 'openwfe/expressions/raw_prog'
|
50
|
+
require 'openwfe/participants/storeparticipant'
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
# The process definition
|
55
|
+
# (using a programmatic process definition instead of an XML process definition)
|
56
|
+
|
57
|
+
class TrackerDefinition < OpenWFE::ProcessDefinition
|
58
|
+
def make
|
59
|
+
|
60
|
+
process_definition :name => "mano_tracker", :revision => "0.2" do
|
61
|
+
_loop do
|
62
|
+
participant "${f:creative}"
|
63
|
+
participant "${f:analyst}"
|
64
|
+
|
65
|
+
_break :if => "${f:done}"
|
66
|
+
#
|
67
|
+
# loops until the analyst sets the value of the field
|
68
|
+
# 'done' to true.
|
69
|
+
end
|
70
|
+
#
|
71
|
+
# 'loop' and 'break' are ruby keywords, they have to be
|
72
|
+
# preceded by an underscore '_' to be used in their
|
73
|
+
# OpenWFEru sense.
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# prepare the engine and the participants
|
80
|
+
|
81
|
+
ANALYSTS = [ "Mano", "Matt", "Moe" ]
|
82
|
+
CREATIVES = [ "Jamie", "Jeff", "John", "Jeremy" ]
|
83
|
+
|
84
|
+
#
|
85
|
+
# instantiate the engine (a transient one is sufficient for the example)
|
86
|
+
|
87
|
+
$engine = OpenWFE::engine.new
|
88
|
+
#
|
89
|
+
# setting up a transient engine
|
90
|
+
|
91
|
+
$analyst_stores = {}
|
92
|
+
$creative_stores = {}
|
93
|
+
#
|
94
|
+
# gathering the stores for our fictitious organization
|
95
|
+
|
96
|
+
def add_stores (names, store_map)
|
97
|
+
names.each do |name|
|
98
|
+
hp = OpenWFE::HashParticipant.new
|
99
|
+
$engine.register_participant(name, hp)
|
100
|
+
store_map[name] = hp
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
add_stores(ANALYSTS, $analyst_stores)
|
105
|
+
add_stores(CREATIVES, $creative_stores)
|
106
|
+
|
107
|
+
#
|
108
|
+
# a quick method for launching a tracker process instance
|
109
|
+
#
|
110
|
+
def launch_tracker (analyst_name, creative_name, title, item_url)
|
111
|
+
|
112
|
+
li = LaunchItem.new(TrackerDefinition)
|
113
|
+
#
|
114
|
+
# preparing a lunchitem ;) around our TrackerDefinition
|
115
|
+
|
116
|
+
li.analyst = analyst_name
|
117
|
+
li.creative = creative_name
|
118
|
+
li.title = title
|
119
|
+
li.item_url = item_url
|
120
|
+
#
|
121
|
+
# filling the workitem with attributes
|
122
|
+
|
123
|
+
$engine.launch(li)
|
124
|
+
end
|
125
|
+
|
126
|
+
# the system is ready...
|
127
|
+
|
128
|
+
|
129
|
+
#
|
130
|
+
# (...)
|
131
|
+
#
|
132
|
+
# Later it can be used as follow
|
133
|
+
|
134
|
+
fei = launch_tracker(
|
135
|
+
"Mano",
|
136
|
+
"Jamie",
|
137
|
+
"new logo for company",
|
138
|
+
"http://openwferu.rubyforge.org/images/openwfe-logo.png")
|
139
|
+
|
140
|
+
puts "launched tracker process #{fei.workflow_instance_id}"
|
141
|
+
|
142
|
+
#
|
143
|
+
# the creative Jamie can browse the items he has to treat with :
|
144
|
+
|
145
|
+
jamie_store = $analyst_stores["Jamie"]
|
146
|
+
|
147
|
+
first_fei = nil
|
148
|
+
|
149
|
+
jamie_store.each do |fei, workitem|
|
150
|
+
first_fei = fei unless fei
|
151
|
+
puts " - #{fei.workflow_instance_id} -- #{workitem.title}"
|
152
|
+
end
|
153
|
+
|
154
|
+
workitem = jamie_store[first_fei]
|
155
|
+
|
156
|
+
# play with the workitem and then send it back to the engine
|
157
|
+
|
158
|
+
workitem.item_url = "some other url"
|
159
|
+
#
|
160
|
+
# actually just changing the item_url
|
161
|
+
|
162
|
+
jamie_store.forward(workitem)
|
163
|
+
|
164
|
+
# ...
|
165
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# showing how to use the scheduler
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
require 'openwfe/util/scheduler'
|
9
|
+
include OpenWFE
|
10
|
+
|
11
|
+
|
12
|
+
def p (msg)
|
13
|
+
t = Time.new
|
14
|
+
puts "#{t.iso8601} -- #{msg}"
|
15
|
+
end
|
16
|
+
#
|
17
|
+
# a small method for displaying the time at the beginning
|
18
|
+
# of each output line
|
19
|
+
|
20
|
+
|
21
|
+
scheduler = Scheduler.new
|
22
|
+
scheduler.start
|
23
|
+
#
|
24
|
+
# create a scheduler instance and start it
|
25
|
+
|
26
|
+
p "started scheduler"
|
27
|
+
|
28
|
+
i = 0
|
29
|
+
|
30
|
+
scheduler.schedule("1-60 * * * *") do
|
31
|
+
p "minute ##{i}"
|
32
|
+
i = i + 1
|
33
|
+
end
|
34
|
+
|
35
|
+
scheduler.schedule_in("2m10s") do
|
36
|
+
p "after 2 minutes and 10 seconds stopping the scheduler and exiting..."
|
37
|
+
scheduler.do_stop
|
38
|
+
end
|
39
|
+
#
|
40
|
+
# using a regular "at" job to stop the scheduler after 4 minutes
|
41
|
+
|
42
|
+
scheduler.join
|
43
|
+
#
|
44
|
+
# align the thread of this program to the scheduler thread
|
45
|
+
# i.e. exit program only when scheduler terminates
|
46
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# showing how to use the scheduler
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
require 'openwfe/util/scheduler'
|
9
|
+
include OpenWFE
|
10
|
+
|
11
|
+
|
12
|
+
def p (msg)
|
13
|
+
t = Time.new
|
14
|
+
puts "#{t.iso8601} -- #{msg}"
|
15
|
+
end
|
16
|
+
#
|
17
|
+
# a small method for displaying the time at the beginning
|
18
|
+
# of each output line
|
19
|
+
|
20
|
+
|
21
|
+
scheduler = Scheduler.new
|
22
|
+
scheduler.start
|
23
|
+
#
|
24
|
+
# create a scheduler instance and start it
|
25
|
+
|
26
|
+
p "started scheduler"
|
27
|
+
|
28
|
+
scheduler.schedule_in("3s") do
|
29
|
+
p "after 3 seconds"
|
30
|
+
end
|
31
|
+
|
32
|
+
scheduler.schedule_in("2s") do
|
33
|
+
p "after 2 seconds"
|
34
|
+
end
|
35
|
+
|
36
|
+
scheduler.schedule_in("5500") do
|
37
|
+
p "after 5500 ms stopping the scheduler and exiting..."
|
38
|
+
scheduler.do_stop
|
39
|
+
end
|
40
|
+
|
41
|
+
#scheduler.schedule_at("x" do
|
42
|
+
#end
|
43
|
+
|
44
|
+
#scheduler.schedule_in("3M4h27m") do
|
45
|
+
# p "3 months, 4 hours and 27 minutes... A bit too much"
|
46
|
+
#end
|
47
|
+
#
|
48
|
+
# showing what the time strings are capable of
|
49
|
+
|
50
|
+
scheduler.join
|
51
|
+
#
|
52
|
+
# align the thread of this program to the scheduler thread
|
53
|
+
# i.e. exit program only when scheduler terminates
|
54
|
+
|
data/lib/openwfe/contextual.rb
CHANGED
@@ -38,9 +38,14 @@
|
|
38
38
|
#
|
39
39
|
# John Mettraux at openwfe.org
|
40
40
|
# Nicolas Modrzyk at openwfe.org
|
41
|
+
#
|
41
42
|
|
42
43
|
module OpenWFE
|
43
44
|
|
45
|
+
#
|
46
|
+
# This mixin helds an application_context field and provides a
|
47
|
+
# lookup method for digging into that context.
|
48
|
+
#
|
44
49
|
module Contextual
|
45
50
|
|
46
51
|
attr_accessor :application_context
|
@@ -61,8 +66,9 @@ module OpenWFE
|
|
61
66
|
end
|
62
67
|
|
63
68
|
#
|
64
|
-
#
|
69
|
+
# Use reflection to instantiate the new service,and
|
65
70
|
# add it to the application context
|
71
|
+
#
|
66
72
|
def init_service (service_name, service_class)
|
67
73
|
@application_context[service_name] = \
|
68
74
|
service_class.new(service_name,@application_context)
|
@@ -40,6 +40,8 @@
|
|
40
40
|
# Nicolas Modrzyk at openwfe.org
|
41
41
|
#
|
42
42
|
|
43
|
+
require 'logger'
|
44
|
+
|
43
45
|
require 'openwfe/workitem'
|
44
46
|
require 'openwfe/rudefinitions'
|
45
47
|
require 'openwfe/service'
|
@@ -65,44 +67,54 @@ module OpenWFE
|
|
65
67
|
|
66
68
|
@application_context[@service_name] = self
|
67
69
|
|
70
|
+
build_scheduler()
|
71
|
+
|
68
72
|
build_expression_map()
|
69
|
-
build_expression_pool()
|
70
73
|
build_expression_storage()
|
74
|
+
build_expression_pool()
|
75
|
+
|
71
76
|
build_participant_map()
|
72
|
-
build_scheduler()
|
73
77
|
|
74
|
-
|
78
|
+
$OWFE_LOG = Logger.new("engine.log") unless $LOG
|
75
79
|
end
|
76
80
|
|
77
81
|
#
|
78
82
|
# Launches a [business] process.
|
79
|
-
# The '
|
83
|
+
# The 'launch_object' param may contain either a LaunchItem instance,
|
80
84
|
# either a String containing the URL of the process definition
|
81
85
|
# to launch (with an empty LaunchItem created on the fly).
|
82
86
|
#
|
83
|
-
def launch (
|
87
|
+
def launch (launch_object)
|
84
88
|
|
85
89
|
launchitem = nil
|
86
90
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
launchitem =
|
91
|
-
|
92
|
-
#nada
|
93
|
-
elsif object.kind_of? String
|
91
|
+
if launch_object.kind_of? OpenWFE::LaunchItem
|
92
|
+
launchitem = launch_object
|
93
|
+
elsif launch_object.kind_of? Class
|
94
|
+
launchitem = LaunchItem.new(launch_object)
|
95
|
+
elsif launch_object.kind_of? String
|
94
96
|
launchitem = OpenWFE::LaunchItem.new
|
95
|
-
if
|
97
|
+
if launch_object[0] == '<'
|
96
98
|
launchitem.workflowDefinitionUrl = "field:__definition"
|
97
|
-
launchitem['definition'] =
|
99
|
+
launchitem['definition'] = launch_object
|
98
100
|
else
|
99
|
-
launchitem.workflowDefinitionUrl =
|
101
|
+
launchitem.workflowDefinitionUrl = launch_object
|
100
102
|
end
|
101
103
|
end
|
102
104
|
|
103
105
|
get_expression_pool.launch(launchitem)
|
104
106
|
end
|
105
107
|
|
108
|
+
#
|
109
|
+
# This method is used to feed a workitem back to the engine (after
|
110
|
+
# it got sent to a worklist or wherever by a participant).
|
111
|
+
# Participant implementations themselves do call this method usually.
|
112
|
+
#
|
113
|
+
def reply (workitem)
|
114
|
+
|
115
|
+
get_expression_pool.reply(workitem.last_expression_id, workitem)
|
116
|
+
end
|
117
|
+
|
106
118
|
#
|
107
119
|
# Registers a participant in this [embedded] engine.
|
108
120
|
# This method is a shortcut to the ParticipantMap method
|
@@ -113,6 +125,37 @@ module OpenWFE
|
|
113
125
|
get_participant_map.register_participant(regex, participant, &block)
|
114
126
|
end
|
115
127
|
|
128
|
+
#
|
129
|
+
# Given a participant name, returns the participant in charge
|
130
|
+
# of handling workitems for that name.
|
131
|
+
# May be useful in some embedded contexts.
|
132
|
+
#
|
133
|
+
def get_participant (participant_name)
|
134
|
+
|
135
|
+
get_participant_map.lookup_participant(participant_name)
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Stopping the engine will stop all the services in the
|
140
|
+
# application context.
|
141
|
+
#
|
142
|
+
def stop
|
143
|
+
|
144
|
+
linfo { "stop() stopping engine '#{@service_name}'" }
|
145
|
+
|
146
|
+
@application_context.each do |name, service|
|
147
|
+
next if name == self.service_name
|
148
|
+
#service.stop if service.respond_to? :stop
|
149
|
+
if service.kind_of? ServiceMixin
|
150
|
+
service.stop
|
151
|
+
linfo do
|
152
|
+
"stop() stopped service '#{service.service_name}' "+
|
153
|
+
"(#{service.class})"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
116
159
|
protected
|
117
160
|
|
118
161
|
#
|
@@ -49,6 +49,7 @@ require 'openwfe/service'
|
|
49
49
|
require 'openwfe/logging'
|
50
50
|
require 'openwfe/rudefinitions'
|
51
51
|
require 'openwfe/flowexpressionid'
|
52
|
+
require 'openwfe/util/stoppable'
|
52
53
|
require 'openwfe/util/lru_cache'
|
53
54
|
require 'openwfe/expressions/environment'
|
54
55
|
require 'openwfe/expressions/raw_xml'
|
@@ -120,16 +121,30 @@ module OpenWFE
|
|
120
121
|
# It relies on an expression storage for actual persistence of the
|
121
122
|
# expressions.
|
122
123
|
#
|
123
|
-
class ExpressionPool
|
124
|
-
include MonitorMixin, OwfeServiceLocator
|
124
|
+
class ExpressionPool
|
125
|
+
include ServiceMixin, MonitorMixin, OwfeServiceLocator, Stoppable
|
125
126
|
|
126
127
|
@@last_given_instance_id = -1
|
127
128
|
#
|
128
129
|
# storing at class level the last workflow instance id given
|
129
130
|
|
130
|
-
def initialize (
|
131
|
-
|
131
|
+
def initialize (service_name, application_context)
|
132
|
+
|
133
|
+
super()
|
134
|
+
|
135
|
+
service_init(service_name, application_context)
|
136
|
+
|
132
137
|
@monitors = MonitorProvider.new(application_context)
|
138
|
+
|
139
|
+
reschedule_a_bit_later
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# Makes sure to call the do_stop() method of the Stoppable mixin
|
144
|
+
#
|
145
|
+
def stop
|
146
|
+
# would an alias be better ?
|
147
|
+
do_stop
|
133
148
|
end
|
134
149
|
|
135
150
|
#
|
@@ -151,17 +166,28 @@ module OpenWFE
|
|
151
166
|
wi = build_workitem(launchitem)
|
152
167
|
|
153
168
|
rawExpression.apply(wi)
|
169
|
+
|
170
|
+
return wi.flow_expression_id
|
154
171
|
end
|
155
172
|
|
156
173
|
#
|
157
174
|
# launches a subprocess
|
158
175
|
#
|
159
176
|
def launch_template \
|
160
|
-
(requesting_expression,
|
177
|
+
(requesting_expression, template, workitem, params=nil)
|
178
|
+
|
179
|
+
#ldebug { "launch_template() of class #{template.class}" }
|
161
180
|
|
162
|
-
|
181
|
+
rawexp = nil
|
182
|
+
|
183
|
+
if template.kind_of? FlowExpressionId
|
184
|
+
rawexp, fei = fetch(template)
|
185
|
+
else # template is of kind RawExpression
|
186
|
+
rawexp = template
|
187
|
+
end
|
188
|
+
|
189
|
+
ldebug { "launch_template() request for #{rawexp.fei.to_debug_s}" }
|
163
190
|
|
164
|
-
rawexp, fei = fetch(template_fei)
|
165
191
|
rawexp = rawexp.dup()
|
166
192
|
rawexp.fei = rawexp.fei.dup()
|
167
193
|
|
@@ -178,6 +204,14 @@ module OpenWFE
|
|
178
204
|
rawexp.fei.workflow_instance_id = \
|
179
205
|
"#{requesting_expression.fei.workflow_instance_id}.0"
|
180
206
|
end
|
207
|
+
|
208
|
+
#ldebug do
|
209
|
+
# p = ""
|
210
|
+
# p = rawexp.parent_id.to_debug_s if rawexp.parent_id
|
211
|
+
# "launch_template()\n"+
|
212
|
+
# " rawexp.fei is #{rawexp.fei.to_debug_s}\n"+
|
213
|
+
# " rawexp.parent_id is #{p}"
|
214
|
+
#end
|
181
215
|
|
182
216
|
#ldebug do
|
183
217
|
# "launch_template() spawning wfid " +
|
@@ -193,6 +227,8 @@ module OpenWFE
|
|
193
227
|
rawexp.store_itself()
|
194
228
|
|
195
229
|
rawexp.apply(workitem)
|
230
|
+
|
231
|
+
return workitem.flow_expression_id
|
196
232
|
end
|
197
233
|
|
198
234
|
#
|
@@ -270,7 +306,13 @@ module OpenWFE
|
|
270
306
|
|
271
307
|
workitem.last_expression_id = fei
|
272
308
|
|
273
|
-
remove(exp, workitem)
|
309
|
+
#remove(exp, workitem)
|
310
|
+
remove(exp)
|
311
|
+
|
312
|
+
#
|
313
|
+
# remove all the children of the expression
|
314
|
+
|
315
|
+
exp.clean_children()
|
274
316
|
|
275
317
|
if not exp.parent_id
|
276
318
|
ldebug do
|
@@ -325,6 +367,7 @@ module OpenWFE
|
|
325
367
|
#
|
326
368
|
def fetch (exp)
|
327
369
|
synchronize do
|
370
|
+
|
328
371
|
fei = exp
|
329
372
|
if exp.kind_of? FlowExpression
|
330
373
|
fei = exp.fei
|
@@ -333,6 +376,9 @@ module OpenWFE
|
|
333
376
|
"Cannot fetch expression with key : "+
|
334
377
|
"'#{fei}' (#{fei.class})"
|
335
378
|
end
|
379
|
+
|
380
|
+
ldebug { "fetch() for #{fei.to_debug_s}" }
|
381
|
+
|
336
382
|
return get_expression_storage()[fei], fei
|
337
383
|
end
|
338
384
|
end
|
@@ -360,8 +406,6 @@ module OpenWFE
|
|
360
406
|
ee.store_itself()
|
361
407
|
end
|
362
408
|
|
363
|
-
ldebug { "fetch_engine_environment() stored new ee" }
|
364
|
-
|
365
409
|
return ee
|
366
410
|
end
|
367
411
|
end
|
@@ -370,7 +414,7 @@ module OpenWFE
|
|
370
414
|
# Removes a flow expression from the pool
|
371
415
|
# (This method is mainly called from the pool itself)
|
372
416
|
#
|
373
|
-
def remove (exp
|
417
|
+
def remove (exp)
|
374
418
|
|
375
419
|
exp, fei = fetch(exp)
|
376
420
|
|
@@ -382,8 +426,8 @@ module OpenWFE
|
|
382
426
|
|
383
427
|
@monitors.delete(fei)
|
384
428
|
|
385
|
-
#get_expression_storage().
|
386
|
-
get_expression_storage().
|
429
|
+
#get_expression_storage().remove(fei, workitem)
|
430
|
+
get_expression_storage().delete(fei)
|
387
431
|
|
388
432
|
if exp.owns_its_environment?
|
389
433
|
remove_environment(exp.environment_id)
|
@@ -392,6 +436,44 @@ module OpenWFE
|
|
392
436
|
end
|
393
437
|
end
|
394
438
|
|
439
|
+
#
|
440
|
+
# This method is called at each expool (engine) [re]start.
|
441
|
+
# It roams through the previously saved (persisted) expressions
|
442
|
+
# to reschedule ones like 'sleep' or 'cron'.
|
443
|
+
#
|
444
|
+
def reschedule
|
445
|
+
synchronize do
|
446
|
+
|
447
|
+
#if is_stopped?
|
448
|
+
# linfo { "reschedule() skipped as expool is stopped" }
|
449
|
+
# return
|
450
|
+
#end
|
451
|
+
#if get_scheduler.is_stopped?
|
452
|
+
# linfo do
|
453
|
+
# "reschedule() skipped as scheduler "+
|
454
|
+
# "#{get_scheduler.object_id} is stopped"
|
455
|
+
# end
|
456
|
+
# return
|
457
|
+
#end
|
458
|
+
|
459
|
+
ldebug { "reschedule() initiating..." }
|
460
|
+
|
461
|
+
get_expression_storage.each_of_kind(Schedulable) do |fe|
|
462
|
+
|
463
|
+
ldebug { "reschedule() for #{fe.fei.to_debug_s}..." }
|
464
|
+
|
465
|
+
fe.reschedule(get_scheduler)
|
466
|
+
end
|
467
|
+
|
468
|
+
ldebug { "reschedule() done." }
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
#
|
473
|
+
# Returns the unique engine_environment FlowExpressionId instance.
|
474
|
+
# There is only one such environment in an engine, hence this
|
475
|
+
# 'singleton' method.
|
476
|
+
#
|
395
477
|
def engine_environment_id ()
|
396
478
|
synchronize do
|
397
479
|
return @eei if @eei
|
@@ -411,6 +493,25 @@ module OpenWFE
|
|
411
493
|
|
412
494
|
protected
|
413
495
|
|
496
|
+
def reschedule_a_bit_later
|
497
|
+
Thread.new do
|
498
|
+
#
|
499
|
+
# Just leaving some time for the initialize() to finish
|
500
|
+
# and let the expression pool get registered in
|
501
|
+
# the application context
|
502
|
+
#
|
503
|
+
begin
|
504
|
+
sleep(0.001)
|
505
|
+
reschedule()
|
506
|
+
rescue
|
507
|
+
lwarn do
|
508
|
+
"reschedule() failed\n"+
|
509
|
+
OpenWFE::exception_to_s($!)
|
510
|
+
end
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
414
515
|
def evaluate_definition (raw_definition, workitem)
|
415
516
|
expression = raw_definition.instantiate(workitem)
|
416
517
|
end
|
@@ -418,7 +519,7 @@ module OpenWFE
|
|
418
519
|
def remove_environment (environment_id)
|
419
520
|
env, fei = fetch(environment_id)
|
420
521
|
env.unbind()
|
421
|
-
get_expression_storage().
|
522
|
+
get_expression_storage().delete(environment_id)
|
422
523
|
end
|
423
524
|
|
424
525
|
def build_workitem (launchitem)
|
@@ -498,6 +599,7 @@ module OpenWFE
|
|
498
599
|
end
|
499
600
|
|
500
601
|
def new_workflow_instance_id ()
|
602
|
+
|
501
603
|
synchronize do
|
502
604
|
wfid = OpenWFE::current_time_millis()
|
503
605
|
wfid = wfid + 1 if wfid == @@last_given_instance_id
|