openwferu 0.9.11 → 0.9.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/README.txt +0 -3
  2. data/examples/engine_template.rb +10 -4
  3. data/lib/openwfe/engine/engine.rb +336 -63
  4. data/lib/openwfe/engine/file_persisted_engine.rb +9 -1
  5. data/lib/openwfe/expool/errorjournal.rb +379 -0
  6. data/lib/openwfe/expool/expressionpool.rb +84 -55
  7. data/lib/openwfe/expool/expstorage.rb +54 -18
  8. data/lib/openwfe/expool/journal.rb +31 -22
  9. data/lib/openwfe/expool/yamlexpstorage.rb +57 -16
  10. data/lib/openwfe/expressions/fe_sequence.rb +1 -1
  11. data/lib/openwfe/expressions/flowexpression.rb +13 -1
  12. data/lib/openwfe/expressions/{fe_raw.rb → raw.rb} +5 -2
  13. data/lib/openwfe/expressions/raw_prog.rb +1 -1
  14. data/lib/openwfe/expressions/raw_xml.rb +1 -1
  15. data/lib/openwfe/expressions/time.rb +2 -0
  16. data/lib/openwfe/flowexpressionid.rb +21 -6
  17. data/lib/openwfe/omixins.rb +37 -14
  18. data/lib/openwfe/participants/atomparticipants.rb +6 -5
  19. data/lib/openwfe/participants/participantmap.rb +2 -0
  20. data/lib/openwfe/rest/controlclient.rb +1 -0
  21. data/lib/openwfe/rudefinitions.rb +5 -1
  22. data/lib/openwfe/storage/yamlfilestorage.rb +7 -3
  23. data/lib/openwfe/util/otime.rb +1 -1
  24. data/lib/openwfe/util/safe.rb +14 -0
  25. data/lib/openwfe/util/scheduler.rb +8 -5
  26. data/lib/openwfe/util/workqueue.rb +9 -2
  27. data/lib/openwfe/utils.rb +18 -0
  28. data/lib/openwfe/version.rb +1 -1
  29. data/test/atom_test.rb +27 -26
  30. data/test/fei_test.rb +3 -3
  31. data/test/file_persistence_test.rb +19 -2
  32. data/test/ft_0c_testname.rb +6 -3
  33. data/test/ft_26_load.rb +14 -7
  34. data/test/ft_26b_load.rb +87 -0
  35. data/test/ft_26c_load.rb +71 -0
  36. data/test/ft_27_getflowpos.rb +22 -3
  37. data/test/ft_34_cancelwfid.rb +3 -2
  38. data/test/ft_42_environments.rb +3 -1
  39. data/test/ft_58_ejournal.rb +119 -0
  40. data/test/ft_59_ps.rb +118 -0
  41. data/test/ft_60_ecancel.rb +87 -0
  42. data/test/ft_tests.rb +4 -0
  43. data/test/hparticipant_test.rb +1 -1
  44. data/test/orest_test.rb +27 -4
  45. data/test/param_test.rb +5 -1
  46. data/test/participant_test.rb +39 -0
  47. data/test/rake_qtest.rb +3 -5
  48. data/test/rest_test.rb +2 -2
  49. data/test/scheduler_test.rb +10 -15
  50. metadata +10 -3
@@ -48,7 +48,7 @@ require 'openwfe/util/lru'
48
48
  require 'openwfe/flowexpressionid'
49
49
 
50
50
  module OpenWFE
51
-
51
+
52
52
  #
53
53
  # This cache uses a LruHash (Least Recently Used) to store expressions.
54
54
  # If an expression is not cached, the 'real storage' is consulted.
@@ -102,7 +102,7 @@ module OpenWFE
102
102
  #ldebug { "[] size is #{@cache.size}" }
103
103
  #ldebug { "[] (sz #{@cache.size}) for #{fei.to_debug_s}" }
104
104
 
105
- fe = @cache[fei]
105
+ fe = @cache[fei.hash]
106
106
  return fe if fe
107
107
 
108
108
  ldebug { "[] (reload) for #{fei.to_debug_s}" }
@@ -114,17 +114,17 @@ module OpenWFE
114
114
  return nil
115
115
  end
116
116
 
117
- @cache[fei] = fe
117
+ @cache[fei.hash] = fe
118
118
 
119
119
  return fe
120
120
  end
121
121
 
122
122
  def []= (fei, fe)
123
- @cache[fei] = fe
123
+ @cache[fei.hash] = fe
124
124
  end
125
125
 
126
126
  def delete (fei)
127
- @cache.delete(fei)
127
+ @cache.delete fei.hash
128
128
  end
129
129
 
130
130
  def length
@@ -148,27 +148,36 @@ module OpenWFE
148
148
  get_real_storage.each_of_kind(kind, &block)
149
149
  end
150
150
 
151
- def each (&block)
152
- #@cache.each do |k, v|
153
- # block.call(k, v)
154
- #end
155
- @cache.each(&block)
151
+ #
152
+ # Passes a block to the expressions currently in the cache.
153
+ #
154
+ def each (wfid_prefix=nil, &block)
155
+
156
+ #@cache.each(&block)
157
+
158
+ if wfid_prefix
159
+ @cache.each do |fei, fexp|
160
+ next unless fei.wfid.match "^#{wfid_prefix}"
161
+ block.call fei, fexp
162
+ end
163
+ else
164
+ @cache.each(&block)
165
+ end
156
166
  end
157
167
 
158
168
  #
159
169
  # This each() just delegates to the real storage each() method.
160
170
  #
161
- def real_each (&block)
162
- #@cache.each do |k, v|
163
- # block.call(k, v)
164
- #end
165
- get_real_storage.each(&block)
171
+ def real_each (wfid_prefix=nil, &block)
172
+
173
+ get_real_storage.each(wfid_prefix, &block)
166
174
  end
167
175
 
168
176
  #
169
177
  # Displays a human-friendly view on this storage
170
178
  #
171
179
  def to_s
180
+
172
181
  expstorage_to_s(self)
173
182
  end
174
183
 
@@ -209,18 +218,45 @@ module OpenWFE
209
218
  end
210
219
  get_expression_pool.add_observer(:remove) do |channel, fei|
211
220
  #ldebug { ":delete for #{fei}" }
212
- self.delete(fei)
221
+ self.delete fei
213
222
  end
214
223
  end
215
224
 
225
+ #def []= (fei, fe)
226
+ # super fei.hash, fe
227
+ #end
228
+ #def [] (fei)
229
+ # super fei.hash
230
+ #end
231
+ #def delete (fei)
232
+ # super fei.hash
233
+ #end
234
+
216
235
  alias :purge :clear
217
236
 
237
+ #
238
+ # Allows to pass a block to each expressions of a given kind (type).
239
+ #
218
240
  def each_of_kind (kind, &block)
219
241
 
220
242
  return unless block
221
243
 
222
244
  self.each_value do |fexp|
223
- block.call(fexp) if fexp.kind_of? kind
245
+ block.call(fexp) if fexp.kind_of?(kind)
246
+ end
247
+ end
248
+
249
+ def each (wfid_prefix=nil, &block)
250
+
251
+ if wfid_prefix
252
+
253
+ super() do |fei, fexp|
254
+ next unless fei.wfid.match "^#{wfid_prefix}"
255
+ block.call fei, fexp
256
+ end
257
+ else
258
+
259
+ super(&block)
224
260
  end
225
261
  end
226
262
 
@@ -229,7 +265,7 @@ module OpenWFE
229
265
  end
230
266
 
231
267
  alias :real_each :each
232
-
268
+
233
269
  end
234
270
 
235
271
  #
@@ -105,21 +105,24 @@ module OpenWFE
105
105
  # flushed.
106
106
  #
107
107
  def queue_event (event, *args)
108
- synchronize do
109
108
 
110
- #ldebug { "queue_event() :#{event}" }
109
+ #ldebug { "queue_event() :#{event}" }
111
110
 
112
- return if event == :stop
113
- return if event == :launch
114
- return if event == :reschedule
111
+ return if event == :stop
112
+ return if event == :launch
113
+ return if event == :reschedule
115
114
 
116
- wfid = extract_fei(args[0]).parent_wfid
117
- #
118
- # maybe args[0] could be a FlowExpression instead
119
- # of a FlowExpressionId instance
120
- #puts "___#{event}__wfid : #{wfid}"
115
+ wfid = extract_fei(args[0]).parent_wfid
116
+ #
117
+ # maybe args[0] could be a FlowExpression instead
118
+ # of a FlowExpressionId instance
119
+ #puts "___#{event}__wfid : #{wfid}"
120
+
121
+ e = serialize_event(event, *args)
121
122
 
122
- e = serialize_event(event, *args)
123
+ bucket = nil
124
+
125
+ synchronize do
123
126
 
124
127
  bucket = get_bucket(wfid)
125
128
  bucket << e
@@ -130,19 +133,25 @@ module OpenWFE
130
133
 
131
134
  bucket.flush
132
135
  @buckets.delete(wfid)
133
-
134
- if @application_context[:keep_journals] == true
135
- #
136
- # 'move' journal to the done/ subdir of journal/
137
- #
138
- FileUtils.cp(
139
- bucket.path,
140
- @donedir + "/" + File.basename(bucket.path))
141
- end
142
-
143
- FileUtils.rm bucket.path
144
136
  end
145
137
  end
138
+ #
139
+ # minimizing the sync block
140
+
141
+ # TODO : spin that off this thread, to the
142
+ # flush thread...
143
+ #
144
+ if event == :terminate
145
+ if @application_context[:keep_journals] == true
146
+ #
147
+ # 'move' journal to the done/ subdir of journal/
148
+ #
149
+ FileUtils.cp(
150
+ bucket.path,
151
+ @donedir + "/" + File.basename(bucket.path))
152
+ end
153
+ FileUtils.rm bucket.path
154
+ end
146
155
  end
147
156
 
148
157
  #
@@ -64,12 +64,6 @@ module OpenWFE
64
64
 
65
65
  def initialize (service_name, application_context)
66
66
 
67
- #path = if (@application_context)
68
- # @application_context[:work_directory]
69
- #else
70
- # DEFAULT_WORK_DIRECTORY
71
- #end
72
- #path = path + '/expool'
73
67
  path = OpenWFE::get_work_directory + '/expool'
74
68
 
75
69
  super(service_name, application_context, path)
@@ -86,8 +80,6 @@ module OpenWFE
86
80
  return unless block
87
81
 
88
82
  exp_names = get_expression_map.get_expression_names(kind)
89
- #require 'pp'
90
- #pp exp_names
91
83
 
92
84
  each_object_path do |path|
93
85
 
@@ -102,9 +94,24 @@ module OpenWFE
102
94
  end
103
95
  end
104
96
 
105
- def each (&block)
106
- each_object do |flow_expression|
107
- block.call(flow_expression.fei, flow_expression)
97
+ #
98
+ # "each flow expression" : this method awaits a block then, for
99
+ # each flow_expression in this storage, calls that block.
100
+ #
101
+ # If wfid_prefix is set, only expressions whose wfid (workflow instance
102
+ # id (process instance id)) will be taken into account.
103
+ #
104
+ def each (wfid_prefix=nil, &block)
105
+
106
+ each_object_path do |path|
107
+
108
+ a = self.class.split_file_path path
109
+ next unless a
110
+ wfid = a[0]
111
+ next if wfid_prefix and ( ! wfid.match "^#{wfid_prefix}")
112
+ flow_expression = load_object path
113
+
114
+ block.call flow_expression.fei, flow_expression
108
115
  end
109
116
  end
110
117
 
@@ -119,7 +126,20 @@ module OpenWFE
119
126
  s << "\n"
120
127
  end
121
128
  s << "==== . ====\n"
122
- return s
129
+ s
130
+ end
131
+
132
+ #
133
+ # Returns nil (if the path doesn't match an stored expression path)
134
+ # or an array [ workflow_instance_id, expression_id, expression_name ].
135
+ #
136
+ # This is a class method (not an instance one).
137
+ #
138
+ def self.split_file_path (path)
139
+
140
+ md = path.match %r{.*/(.*)__([\d.]*)_(.*).yaml}
141
+ return nil unless md
142
+ [ md[1], md[2], md[3] ]
123
143
  end
124
144
 
125
145
  protected
@@ -149,7 +169,6 @@ module OpenWFE
149
169
 
150
170
  wfid = fei.parent_workflow_instance_id
151
171
 
152
- #a_wfid = OpenWFE::split_wfid(wfid)
153
172
  a_wfid = get_wfid_generator.split_wfid(wfid)
154
173
 
155
174
  @basepath +
@@ -160,6 +179,10 @@ module OpenWFE
160
179
  fei.expression_name + ".yaml"
161
180
  end
162
181
 
182
+ #
183
+ # Returns true if the path points to a file containing an
184
+ # expression whose name is in exp_names.
185
+ #
163
186
  def matches (path, exp_names)
164
187
 
165
188
  exp_names.each do |exp_name|
@@ -167,7 +190,7 @@ module OpenWFE
167
190
  if OpenWFE::ends_with(path, "_#{exp_name}.yaml")
168
191
  end
169
192
 
170
- return false
193
+ false
171
194
  end
172
195
  end
173
196
 
@@ -181,6 +204,9 @@ module OpenWFE
181
204
  #
182
205
  # the frequency at which the event queue should be processed
183
206
 
207
+ #
208
+ # TODO : make this configurable (param in the apcontext ?)
209
+
184
210
  def initialize (service_name, application_context)
185
211
 
186
212
  super
@@ -221,7 +247,7 @@ module OpenWFE
221
247
  # calls process_queue() before the call the super class each()
222
248
  # method
223
249
  #
224
- def each (&block)
250
+ def each (wfid_prefix=nil, &block)
225
251
 
226
252
  process_queue()
227
253
  super
@@ -229,6 +255,9 @@ module OpenWFE
229
255
 
230
256
  protected
231
257
 
258
+ #
259
+ # starts the thread that does the actual persistence.
260
+ #
232
261
  def start_processing_thread
233
262
 
234
263
  @thread_id = get_scheduler.schedule_every(FREQ) do
@@ -236,6 +265,9 @@ module OpenWFE
236
265
  end
237
266
  end
238
267
 
268
+ #
269
+ # queues an event for later (well within a second) persistence
270
+ #
239
271
  def queue (event, fei, fe=nil)
240
272
  synchronize do
241
273
 
@@ -251,7 +283,10 @@ module OpenWFE
251
283
  end
252
284
  end
253
285
 
254
- def process_queue ()
286
+ #
287
+ # the actual "do persist" order
288
+ #
289
+ def process_queue
255
290
 
256
291
  return unless @events.size > 0
257
292
  #
@@ -296,6 +331,12 @@ module OpenWFE
296
331
  end
297
332
  end
298
333
 
334
+ #
335
+ # Adds the queue() method as an observer to the update and remove
336
+ # events of the expression pool.
337
+ # :update and :remove mean changes to expressions in the persistence
338
+ # that's why they are observed.
339
+ #
299
340
  def observe_expool
300
341
 
301
342
  get_expression_pool.add_observer(:update) do |event, fei, fe|
@@ -109,7 +109,7 @@ module OpenWFE
109
109
  @current_child_id += 1
110
110
  end
111
111
 
112
- return nil
112
+ nil
113
113
  #
114
114
  # did not find any child expression
115
115
  end
@@ -135,7 +135,7 @@ module OpenWFE
135
135
  next if child.kind_of? String
136
136
 
137
137
  i = get_expression_pool().cancel(child)
138
- inflowitem = i if not inflowitem
138
+ inflowitem = i unless inflowitem
139
139
  end
140
140
 
141
141
  inflowitem
@@ -463,6 +463,18 @@ module OpenWFE
463
463
  end
464
464
  end
465
465
 
466
+ #
467
+ # Removes a child from the expression children list.
468
+ #
469
+ def remove_child (child_fei)
470
+
471
+ fei = @children.delete child_fei
472
+
473
+ store_itself if fei
474
+ #
475
+ # store_itself if the child was really removed.
476
+ end
477
+
466
478
  #
467
479
  # Currently only used by dollar.rb and its ${r:some_ruby_code},
468
480
  # returns the binding in this flow expression.
@@ -81,7 +81,6 @@ module OpenWFE
81
81
 
82
82
  attributes = extract_attributes() unless attributes
83
83
 
84
-
85
84
  expression = exp_class.new(
86
85
  @fei,
87
86
  @parent_id,
@@ -145,7 +144,11 @@ module OpenWFE
145
144
  expression = instantiate_real_expression(
146
145
  workitem, exp_class, attributes)
147
146
 
148
- expression.apply_time = OpenWFE::now()
147
+ #expression.apply_time = OpenWFE::now()
148
+ #
149
+ # This method is extremely costly, now avoiding it
150
+
151
+ expression.apply_time = Time.now
149
152
 
150
153
  expression.apply workitem
151
154
  end
@@ -42,7 +42,7 @@
42
42
  require 'rexml/document'
43
43
 
44
44
  require 'openwfe/utils'
45
- require 'openwfe/expressions/fe_raw'
45
+ require 'openwfe/expressions/raw'
46
46
  require 'openwfe/expressions/simplerep'
47
47
 
48
48
 
@@ -41,7 +41,7 @@
41
41
 
42
42
  require 'rexml/document'
43
43
 
44
- require 'openwfe/expressions/fe_raw'
44
+ require 'openwfe/expressions/raw'
45
45
 
46
46
 
47
47
  module OpenWFE
@@ -71,6 +71,8 @@ module OpenWFE
71
71
  unschedule()
72
72
 
73
73
  super()
74
+
75
+ @applied_workitem
74
76
  end
75
77
  end
76
78
 
@@ -74,6 +74,8 @@ module OpenWFE
74
74
  #
75
75
  alias :wfid :workflow_instance_id
76
76
  alias :wfid= :workflow_instance_id=
77
+ alias :expid :expression_id
78
+ alias :expid= :expression_id=
77
79
 
78
80
  #
79
81
  # Overrides the classical to_s()
@@ -107,15 +109,21 @@ module OpenWFE
107
109
  def == (other)
108
110
  return false if not other.kind_of?(FlowExpressionId)
109
111
 
110
- @owfe_version == other.owfe_version and
111
- @engine_id == other.engine_id and
112
- @initial_engine_id == other.initial_engine_id and
112
+ #return self.to_s == other.to_s
113
+ # no perf gain
114
+
115
+ @workflow_instance_id == other.workflow_instance_id and
116
+ @expression_id == other.expression_id and
113
117
  @workflow_definition_url == other.workflow_definition_url and
114
- @workflow_definition_name == other.workflow_definition_name and
115
118
  @workflow_definition_revision == other.workflow_definition_revision and
116
- @workflow_instance_id == other.workflow_instance_id and
119
+ @workflow_definition_name == other.workflow_definition_name and
117
120
  @expression_name == other.expression_name and
118
- @expression_id == other.expression_id
121
+ @owfe_version == other.owfe_version and
122
+ @engine_id == other.engine_id and
123
+ @initial_engine_id == other.initial_engine_id
124
+ #
125
+ # Make sure to put on top of the 'and' the things that
126
+ # change the most...
119
127
  end
120
128
 
121
129
  #
@@ -230,6 +238,13 @@ module OpenWFE
230
238
 
231
239
  fei
232
240
  end
241
+
242
+ #
243
+ # An alias for to_fei(string)
244
+ #
245
+ def FlowExpressionId.from_s (string)
246
+ FlowExpressionId.to_fei(string)
247
+ end
233
248
  end
234
249
 
235
250
  end
@@ -49,21 +49,44 @@ module OpenWFE
49
49
  #
50
50
  module FeiMixin
51
51
 
52
- #
53
- # Makes sure to return a FlowExpressionId instance.
54
- #
55
- def extract_fei (object)
56
-
57
- if object.kind_of?(FlowExpressionId)
58
- object
59
- elsif object.kind_of?(FlowExpression) or object.kind_of?(InFlowItem)
60
- object.fei
61
- elsif object.kind_of?(String)
62
- FlowExpressionId.to_fei object
63
- else
64
- raise "cannot extract FlowExpressionId out of #{object.inspect}"
52
+ protected
53
+
54
+ #
55
+ # Makes sure to return a FlowExpressionId instance.
56
+ #
57
+ def extract_fei (object)
58
+
59
+ if object.kind_of?(FlowExpressionId)
60
+
61
+ object
62
+
63
+ elsif object.kind_of?(FlowExpression) or
64
+ object.kind_of?(InFlowItem)
65
+
66
+ object.fei
67
+
68
+ elsif object.kind_of?(String)
69
+
70
+ FlowExpressionId.to_fei object
71
+
72
+ else
73
+
74
+ raise \
75
+ "cannot extract FlowExpressionId "+
76
+ "out of #{object.inspect}"
77
+ end
65
78
  end
66
- end
79
+
80
+ #
81
+ # A small method for ensuring we have a workflow instance id.
82
+ #
83
+ def to_wfid (fei_or_wfid)
84
+ wfid = fei_or_wfid
85
+ wfid = wfid.parent_wfid if wfid.kind_of?(FlowExpressionId)
86
+ wfid.to_s
87
+ end
88
+
89
+ alias :extract_wfid :to_wfid
67
90
  end
68
91
 
69
92
  end
@@ -137,9 +137,9 @@ module OpenWFE
137
137
  @feed = @feed[0, @max_item_count] \
138
138
  if @feed.length > @max_item_count
139
139
 
140
- publish(workitem)
140
+ publish workitem
141
141
 
142
- reply_to_engine(workitem)
142
+ reply_to_engine workitem
143
143
  end
144
144
 
145
145
  protected
@@ -149,7 +149,8 @@ module OpenWFE
149
149
  fe = get_flow_expression(workitem)
150
150
 
151
151
  template = if @block_template
152
- @block_template.call(fe, self, workitem)
152
+ #@block_template.call(fe, self, workitem)
153
+ call_block @block_template, workitem
153
154
  elsif @template
154
155
  if @template.kind_of? File
155
156
  @template.readlines
@@ -160,7 +161,7 @@ module OpenWFE
160
161
  "(no template given)"
161
162
  end
162
163
 
163
- return OpenWFE::dosub(template, fe, workitem)
164
+ OpenWFE::dosub(template, fe, workitem)
164
165
  end
165
166
 
166
167
  #
@@ -168,7 +169,7 @@ module OpenWFE
168
169
  #
169
170
  def publish (workitem)
170
171
  synchronize do
171
- filename = "atom_#{workitem.participant_name}.xml"
172
+ filename = "work/atom_#{workitem.participant_name}.xml"
172
173
  f = File.open(filename, "w")
173
174
  f << @feed.to_s
174
175
  f.close()
@@ -134,6 +134,8 @@ module OpenWFE
134
134
 
135
135
  #ldebug { "lookup_participant() '#{participant_name}'" }
136
136
 
137
+ participant_name = participant_name.to_s
138
+
137
139
  @participants.each do |tuple|
138
140
  return tuple[1] if tuple[0].match(participant_name)
139
141
  end
@@ -77,6 +77,7 @@ module OpenWFE
77
77
  r = self.get('getflowposition', nil, params)
78
78
  decode(r)
79
79
  end
80
+ alias :get_flow_stack :get_flow_position
80
81
 
81
82
  #
82
83
  # Cancels a given expression (and potentially its whole subtree)
@@ -57,6 +57,7 @@ module OpenWFE
57
57
  S_EXPRESSION_STORAGE = 'expressionStorage'
58
58
  S_PARTICIPANT_MAP = 'participantMap'
59
59
  S_SCHEDULER = 'scheduler'
60
+ S_ERROR_JOURNAL = 'errorJournal'
60
61
 
61
62
  #
62
63
  # some special expression names
@@ -110,6 +111,9 @@ module OpenWFE
110
111
  def get_participant_map
111
112
  @application_context[S_PARTICIPANT_MAP]
112
113
  end
114
+ def get_error_journal
115
+ @application_context[S_ERROR_JOURNAL]
116
+ end
113
117
 
114
118
  #
115
119
  # Returns the 'journal' service (or nil if there is no
@@ -129,7 +133,7 @@ module OpenWFE
129
133
  result << v \
130
134
  if OpenWFE::starts_with(k.to_s, S_EXPRESSION_STORAGE)
131
135
  end
132
- return result
136
+ result
133
137
  end
134
138
  end
135
139