libis-workflow 2.0.36 → 2.0.37

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 391021b367fd4a087777f80abc4cc98b7602ac012207155bec4bf0c2f1cd9f9f
4
- data.tar.gz: 053a3ee71843fec6efcc98d0beb00dec6c5cd9c6a140b2e5f589384b9172e299
3
+ metadata.gz: d248c18f7b5ec05c2a28bd7121a31d6c9f3f00c73a4e688c7fe00b4fdf12dde8
4
+ data.tar.gz: cfd5c563241f5a7bf2a76c287f7411ef1b81e720fa29886594e39d8f66a195dc
5
5
  SHA512:
6
- metadata.gz: 6ca558020759c70cb7acd8e0b241f08e6b17b0f391a9616c726760c9ea1ecd89cc6782b8a4570b826c9daef03be984b17a36c15ae15aa047b599f433b6c10445
7
- data.tar.gz: 7b426682ab3e15e292215fda755307028d9a5c6abc4ca3facad3f619f46f53a4394b67c607c6bd362eac67edbb31e7d184cf5271af780e7f965f52b0737c5c9e
6
+ metadata.gz: 1103e4fdff7de541a410c065605c220fd9890a7e4b17cb38ea965f1bf3246d415f99c70f67a18ed604e9ad2a009c47a5d252edce46f5114d91057d4e2a1d771f
7
+ data.tar.gz: 0a30fa5acc5df9709ab742b5331e7a597b189ee563a0c08f12e072b72c6c748c85877d66f868554d6cc80c0ad5e23b1d663f0135e0fe184fd1b16be9a47fb93a
data/README.md CHANGED
@@ -103,6 +103,8 @@ The ::Libis::Workflow::Task base class allready defines the following parameters
103
103
  * abort_recursion_on_failure: Stop processing items recursively if one item fails. Default: false
104
104
  * retry_count: Number of times to retry the task. Default: 0
105
105
  * retry_interval: Number of seconds to wait between retries. Default: 10
106
+ * run_always: If set and true will cause the task to be always executed, even if previous tasks have failed or during
107
+ a retry if the task completed successfully before.
106
108
 
107
109
  If 'class' is not present, the default '::Libis::Workflow::TaskGroup' with the given name will be instantiated, which
108
110
  performs each sub-task on the item.
@@ -114,6 +116,10 @@ the work item to process on. See the chapter on 'Tasks' below for more informati
114
116
  Note that a task with custom processing will not execute sub-tasks. If you configured a processing task with subtasks
115
117
  an exception will be thrown when trying to execute the job.
116
118
 
119
+ The run_always option will only be evaluated within the current TaskGroup. This means that if the parent task was not
120
+ configure with run_always set to true and the parent task completed successfully previously, the whole subtree of tasks
121
+ will not be executed during a retry.
122
+
117
123
  ##### Input variable definition
118
124
 
119
125
  The input variables define parameters for the workflow. When a job is executed, it can provide values for any of these
@@ -1,4 +1,5 @@
1
1
  require 'libis/tools/parameter'
2
+ require 'libis/tools/extend/hash'
2
3
 
3
4
  module Libis
4
5
  module Workflow
@@ -44,6 +45,7 @@ module Libis
44
45
  end
45
46
 
46
47
  def configure(cfg = {})
48
+ cfg.key_symbols_to_strings!(recursive: true)
47
49
  self.name ||= ''
48
50
  self.description ||= ''
49
51
  self.input ||= {}
@@ -76,6 +76,7 @@ module Libis
76
76
  end
77
77
 
78
78
  def configure(cfg)
79
+ cfg.key_symbols_to_strings!(recursive: true)
79
80
  self.name = cfg.delete('name') || self.class.name
80
81
  self.description = cfg.delete('description') || ''
81
82
  self.config['input'] = {}
@@ -21,6 +21,7 @@ module Libis
21
21
  parameter abort_recursion_on_failure: false, description: 'Stop processing items recursively if one item fails.'
22
22
  parameter retry_count: 0, description: 'Number of times to retry the task if waiting for another process.'
23
23
  parameter retry_interval: 10, description: 'Number of seconds to wait between retries.'
24
+ parameter run_always: false, description: 'Always run this task, even if previous tasks have failed.'
24
25
 
25
26
  def self.task_classes
26
27
  # noinspection RubyArgCount
@@ -44,17 +45,19 @@ module Libis
44
45
  check_item_type ::Libis::Workflow::Base::WorkItem, item
45
46
  self.workitem = item
46
47
 
47
- case action
48
- when :retry
49
- if item.check_status(:DONE, namepath)
50
- debug 'Retry: skipping task %s because it has finished successfully.', item, namepath
51
- return item
52
- end
53
- when :failed
54
- return item
55
- else
56
- # type code here
57
- end
48
+ # case action
49
+ # when :retry
50
+ # if !parameter(:run_always) && item.check_status(:DONE, namepath)
51
+ # debug 'Retry: skipping task %s because it has finished successfully.', item, namepath
52
+ # return item
53
+ # end
54
+ # when :failed
55
+ # return item unless parameter(:run_always)
56
+ # else
57
+ # # type code here
58
+ # end
59
+
60
+ return item if action == :failed && !parameter(:run_always)
58
61
 
59
62
  (parameter(:retry_count) + 1).times do
60
63
 
@@ -64,7 +67,7 @@ module Libis
64
67
  # noinspection RubyScope
65
68
  case item.status(namepath)
66
69
  when :DONE
67
- self.action = :run
70
+ # self.action = :run
68
71
  return item
69
72
  when :ASYNC_WAIT
70
73
  self.action = :retry
@@ -158,7 +161,7 @@ module Libis
158
161
  def run_item(item)
159
162
  @item_skipper = false
160
163
 
161
- return item if item.status(namepath) == :DONE
164
+ return item if item.status(namepath) == :DONE && !parameter(:run_always)
162
165
 
163
166
  pre_process(item)
164
167
 
@@ -39,14 +39,22 @@ module Libis
39
39
 
40
40
  status_count = Hash.new(0)
41
41
  item.status_progress(self.namepath, 0, tasks.count)
42
+ continue = true
42
43
  tasks.each_with_index do |task, i|
44
+ unless task.parameter(:run_always)
45
+ next unless continue
46
+ if item.status(task.namepath) == :DONE && item.get_run.action == :retry
47
+ debug 'Retry: skipping task %s because it has finished successfully.', item, task.namepath
48
+ next
49
+ end
50
+ end
43
51
  info 'Running subtask (%d/%d): %s', item, i+1, tasks.size, task.name
44
52
  new_item = task.run item
45
53
  item = new_item if new_item.is_a?(Libis::Workflow::WorkItem)
46
54
  item.status_progress(self.namepath, i+1)
47
55
  item_status = item.status(task.namepath)
48
56
  status_count[item_status] += 1
49
- break if parameter(:abort_on_failure) && item_status != :DONE
57
+ continue = false if parameter(:abort_on_failure) && item_status != :DONE
50
58
  end
51
59
 
52
60
  substatus_check(status_count, item, 'task')
@@ -1,5 +1,5 @@
1
1
  module Libis
2
2
  module Workflow
3
- VERSION = '2.0.36' unless const_defined? :VERSION # the guard is against a redefinition warning that happens on Travis
3
+ VERSION = '2.0.37' unless const_defined? :VERSION # the guard is against a redefinition warning that happens on Travis
4
4
  end
5
5
  end
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'rspec', '~> 3.1'
33
33
  spec.add_development_dependency 'simplecov', '~> 0.9'
34
34
  spec.add_development_dependency 'coveralls', '~> 0.7'
35
+ spec.add_development_dependency 'awesome_print'
35
36
 
36
37
  spec.add_runtime_dependency 'libis-tools', '~> 0.9'
37
38
  spec.add_runtime_dependency 'sidekiq', '~> 4.0'
@@ -0,0 +1,13 @@
1
+ require 'libis/exceptions'
2
+ require 'libis/workflow'
3
+
4
+ class FinalTask < ::Libis::Workflow::Task
5
+
6
+ def process(item)
7
+ return unless item.is_a? TestFileItem
8
+
9
+ info "Final processing of #{item.name}"
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,31 @@
1
+ require 'libis/exceptions'
2
+ require 'libis/workflow'
3
+
4
+ class ProcessingTask < ::Libis::Workflow::Task
5
+
6
+ parameter config: 'success', constraint: %w'success async_halt fail error abort',
7
+ description: 'determines the outcome of the processing'
8
+
9
+ def process(item)
10
+ return unless item.is_a? TestFileItem
11
+
12
+ case parameter(:config).downcase.to_sym
13
+ when :success
14
+ info 'Task success'
15
+ when :async_halt
16
+ set_status(item, :ASYNC_HALT)
17
+ error "Task failed with async_halt status"
18
+ when :fail
19
+ set_status(item, :FAILED)
20
+ error "Task failed with failed status"
21
+ when :error
22
+ raise Libis::WorkflowError, "Task failed with WorkflowError exception"
23
+ when :abort
24
+ raise Libis::WorkflowAbort, "Task failed with WorkflowAbort exception"
25
+ else
26
+ info 'Task success'
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -1,11 +1,34 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
3
  require 'stringio'
4
+ require 'awesome_print'
4
5
 
5
- describe 'TestWorkflow' do
6
+ basedir = File.absolute_path File.join(File.dirname(__FILE__))
7
+ dirname = File.join(basedir, 'items')
6
8
 
7
- basedir = File.absolute_path File.join(File.dirname(__FILE__))
8
- dirname = File.join(basedir, 'items')
9
+ def check_output(logoutput, sample_out)
10
+ sample_out = sample_out.lines.to_a.map {|x| x.strip}
11
+ output = logoutput.string.lines.to_a.map {|x| x[/(?<=\] ).*/].strip}
12
+
13
+ puts 'output:'
14
+ ap output
15
+
16
+ expect(output.size).to eq sample_out.size
17
+ output.each_with_index do |o, i|
18
+ expect(o).to eq sample_out[i]
19
+ end
20
+ end
21
+
22
+ def check_status_log(status_log, sample_status_log)
23
+ puts 'status_log:'
24
+ status_log.each { |e| ap e }
25
+ expect(status_log.size).to eq sample_status_log.size
26
+ sample_status_log.each_with_index do |h, i|
27
+ h.keys.each {|key| expect(status_log[i][key.to_s]).to eq h[key]}
28
+ end
29
+ end
30
+
31
+ context 'TestWorkflow' do
9
32
 
10
33
  before :each do
11
34
 
@@ -19,26 +42,26 @@ describe 'TestWorkflow' do
19
42
  end
20
43
  end
21
44
 
22
- let(:logoutput) { ::Libis::Workflow::Config.logger.appenders.first.sio }
45
+ let(:logoutput) {::Libis::Workflow::Config.logger.appenders.first.sio}
23
46
 
24
47
  let(:workflow) {
25
48
  workflow = ::Libis::Workflow::Workflow.new
26
49
  workflow.configure(
27
- 'name' => 'TestWorkflow',
28
- 'description' => 'Workflow for testing',
29
- 'tasks' => [
30
- {'class' => 'CollectFiles', 'recursive' => true},
50
+ name: 'TestWorkflow',
51
+ description: 'Workflow for testing',
52
+ tasks: [
53
+ {class: 'CollectFiles', recursive: true},
31
54
  {
32
- 'name' => 'ProcessFiles', 'recursive' => false,
33
- 'tasks' => [
34
- {'class' => 'ChecksumTester', 'recursive' => true},
35
- {'class' => 'CamelizeName', 'recursive' => true}
55
+ name: 'ProcessFiles', recursive: false,
56
+ tasks: [
57
+ {class: 'ChecksumTester', recursive: true},
58
+ {class: 'CamelizeName', :recursive => true}
36
59
  ]
37
60
  }
38
61
  ],
39
- 'input' => {
40
- 'dirname' => {'default' => '.', 'propagate_to' => 'CollectFiles#location'},
41
- 'checksum_type' => {'default' => 'SHA1', 'propagate_to' => 'ChecksumTester'}
62
+ input: {
63
+ dirname: {default: '.', propagate_to: 'CollectFiles#location'},
64
+ checksum_type: {default: 'SHA1', propagate_to: 'ChecksumTester'}
42
65
  }
43
66
  )
44
67
  workflow
@@ -47,12 +70,12 @@ describe 'TestWorkflow' do
47
70
  let(:job) {
48
71
  job = ::Libis::Workflow::Job.new
49
72
  job.configure(
50
- 'name' => 'TestJob',
51
- 'description' => 'Job for testing',
52
- 'workflow' => workflow,
53
- 'run_object' => 'TestRun',
54
- 'input' => {'dirname' => dirname, 'checksum_type' => 'SHA256'},
55
- )
73
+ name: 'TestJob',
74
+ description: 'Job for testing',
75
+ workflow: workflow,
76
+ run_object: 'TestRun',
77
+ input: {dirname: dirname, checksum_type: 'SHA256'},
78
+ )
56
79
  job
57
80
  }
58
81
 
@@ -81,8 +104,9 @@ describe 'TestWorkflow' do
81
104
  end
82
105
 
83
106
  it 'should return expected debug output' do
107
+ run = job.execute
84
108
 
85
- sample_out = <<STR
109
+ check_output logoutput, <<STR
86
110
  INFO -- Run - TestRun : Ingest run started.
87
111
  INFO -- Run - TestRun : Running subtask (1/2): CollectFiles
88
112
  DEBUG -- CollectFiles - TestRun : Processing subitem (1/1): items
@@ -109,46 +133,559 @@ DEBUG -- ProcessFiles/CamelizeName - TestRun : 1 of 1 subitems passed
109
133
  INFO -- ProcessFiles - TestRun : Done
110
134
  INFO -- Run - TestRun : Done
111
135
  STR
112
- sample_out = sample_out.lines.to_a
113
-
114
- run = job.execute
115
- output = logoutput.string.lines.to_a
116
-
117
- # puts output
118
136
 
119
- expect(output.size).to eq sample_out.size
120
- output.each_with_index do |o, i|
121
- expect(o[/(?<=\] ).*/].strip).to eq sample_out[i].strip
122
- end
123
-
124
- # run.status_log.each { |e| puts e }
125
- expect(run.status_log.size).to eq 5
126
- expect(run.items.first.status_log.size).to eq 3
127
-
128
- [
137
+ check_status_log run.status_log, [
129
138
  {task: 'Run', status: :DONE, progress: 2, max: 2},
130
139
  {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
131
140
  {task: 'ProcessFiles', status: :DONE, progress: 2, max: 2},
132
141
  {task: 'ProcessFiles/ChecksumTester', status: :DONE, progress: 1, max: 1},
133
142
  {task: 'ProcessFiles/CamelizeName', status: :DONE, progress: 1, max: 1},
134
- ].each_with_index do |h, i|
135
- h.keys.each { |key| expect(run.status_log[i][key.to_s]).to eq h[key] }
136
- end
143
+ ]
137
144
 
138
- [
145
+ check_status_log run.items.first.status_log, [
139
146
  {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
140
147
  {task: 'ProcessFiles/ChecksumTester', status: :DONE, progress: 3, max: 3},
141
148
  {task: 'ProcessFiles/CamelizeName', status: :DONE, progress: 3, max: 3},
142
- ].each_with_index do |h, i|
143
- h.keys.each { |key| expect(run.items.first.status_log[i][key.to_s]).to eq h[key] }
144
- end
149
+ ]
145
150
 
146
- [
151
+ check_status_log run.items.first.items.first.status_log, [
147
152
  {task: 'CollectFiles', status: :DONE, progress: nil, max: nil},
148
153
  {task: 'ProcessFiles/ChecksumTester', status: :DONE, progress: nil, max: nil},
149
154
  {task: 'ProcessFiles/CamelizeName', status: :DONE, progress: nil, max: nil},
150
- ].each_with_index do |h, i|
151
- h.keys.each { |key| expect(run.items.first.first.status_log[i][key.to_s]).to eq h[key] }
155
+ ]
156
+
157
+ end
158
+
159
+ end
160
+
161
+ context 'Test run_always' do
162
+
163
+ before :each do
164
+
165
+ # noinspection RubyResolve
166
+ ::Libis::Workflow.configure do |cfg|
167
+ cfg.itemdir = dirname
168
+ cfg.taskdir = File.join(basedir, 'tasks')
169
+ cfg.workdir = File.join(basedir, 'work')
170
+ cfg.logger.appenders =
171
+ ::Logging::Appenders.string_io('StringIO', layout: ::Libis::Tools::Config.get_log_formatter)
172
+ cfg.logger.level = :INFO
173
+ end
174
+ end
175
+
176
+ let(:logoutput) {::Libis::Workflow::Config.logger.appenders.first.sio}
177
+
178
+ let(:workflow) {
179
+ workflow = ::Libis::Workflow::Workflow.new
180
+ workflow.configure(
181
+ name: 'TestRunAlways',
182
+ description: 'Workflow for testing run_always options',
183
+ tasks: [
184
+ {class: 'CollectFiles', recursive: true},
185
+ {class: 'ProcessingTask', recursive: true},
186
+ {class: 'FinalTask', recursive: true}
187
+ ],
188
+ input: {
189
+ dirname: {default: '.', propagate_to: 'CollectFiles#location'},
190
+ processing: {default: 'success', propagate_to: 'ProcessingTask#config'},
191
+ force_run: {default: false, propagate_to: 'FinalTask#run_always'}
192
+ }
193
+ )
194
+ workflow
195
+ }
196
+
197
+ let(:processing) {'success'}
198
+ let(:force_run) {false}
199
+
200
+ let(:job) {
201
+ job = ::Libis::Workflow::Job.new
202
+ job.configure(
203
+ name: 'TestJob',
204
+ description: 'Job for testing run_always',
205
+ workflow: workflow,
206
+ run_object: 'TestRun',
207
+ input: {dirname: dirname, processing: processing, force_run: force_run},
208
+ )
209
+ job
210
+ }
211
+
212
+ let(:run) {job.execute}
213
+
214
+ context 'without forcing final task' do
215
+ let(:force_run) {false}
216
+
217
+ context 'when processing successfully' do
218
+ let(:processing) {'success'}
219
+
220
+ it 'should run final task' do
221
+ run
222
+
223
+ check_output logoutput, <<STR
224
+ INFO -- Run - TestRun : Ingest run started.
225
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
226
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
227
+ INFO -- ProcessingTask - TestRun : Task success
228
+ INFO -- ProcessingTask - TestRun : Task success
229
+ INFO -- ProcessingTask - TestRun : Task success
230
+ INFO -- Run - TestRun : Running subtask (3/3): FinalTask
231
+ INFO -- FinalTask - TestRun : Final processing of test_dir_item.rb
232
+ INFO -- FinalTask - TestRun : Final processing of test_file_item.rb
233
+ INFO -- FinalTask - TestRun : Final processing of test_run.rb
234
+ INFO -- Run - TestRun : Done
235
+ STR
236
+
237
+ check_status_log run.status_log, [
238
+ {task: 'Run', status: :DONE, progress: 3, max: 3},
239
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
240
+ {task: 'ProcessingTask', status: :DONE, progress: 1, max: 1},
241
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
242
+ ]
243
+
244
+ check_status_log run.items.first.status_log, [
245
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
246
+ {task: 'ProcessingTask', status: :DONE, progress: 3, max: 3},
247
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
248
+ ]
249
+
250
+ check_status_log run.items.first.items.first.status_log, [
251
+ {task: 'CollectFiles', status: :DONE},
252
+ {task: 'ProcessingTask', status: :DONE},
253
+ {task: 'FinalTask', status: :DONE},
254
+ ]
255
+
256
+ end
257
+
258
+ end
259
+
260
+ context 'when stopped with async_halt' do
261
+ let(:processing) {'async_halt'}
262
+
263
+ it 'should not run final task' do
264
+ run
265
+
266
+ check_output logoutput, <<STR
267
+ INFO -- Run - TestRun : Ingest run started.
268
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
269
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
270
+ ERROR -- ProcessingTask - TestRun : Task failed with async_halt status
271
+ ERROR -- ProcessingTask - TestRun : Task failed with async_halt status
272
+ ERROR -- ProcessingTask - TestRun : Task failed with async_halt status
273
+ WARN -- ProcessingTask - items : 3 subitem(s) halted in async process
274
+ WARN -- ProcessingTask - TestRun : 1 subitem(s) halted in async process
275
+ WARN -- Run - TestRun : 1 subtask(s) halted in async process
276
+ INFO -- Run - TestRun : Waiting for halted async process
277
+ STR
278
+
279
+ check_status_log run.status_log ,[
280
+ {task: 'Run', status: :ASYNC_HALT, progress: 2, max: 3},
281
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
282
+ {task: 'ProcessingTask', status: :ASYNC_HALT, progress: 1, max: 1},
283
+ ]
284
+
285
+ check_status_log run.items.first.status_log, [
286
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
287
+ {task: 'ProcessingTask', status: :ASYNC_HALT, progress: 3, max: 3},
288
+ ]
289
+
290
+ check_status_log run.items.first.items.first.status_log, [
291
+ {task: 'CollectFiles', status: :DONE},
292
+ {task: 'ProcessingTask', status: :ASYNC_HALT},
293
+ ]
294
+
295
+ end
296
+
297
+ end
298
+
299
+ context 'when stopped with fail' do
300
+ let(:processing) {'fail'}
301
+
302
+ it 'should not run final task' do
303
+ run
304
+
305
+ check_output logoutput, <<STR
306
+ INFO -- Run - TestRun : Ingest run started.
307
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
308
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
309
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
310
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
311
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
312
+ ERROR -- ProcessingTask - items : 3 subitem(s) failed
313
+ ERROR -- ProcessingTask - TestRun : 1 subitem(s) failed
314
+ ERROR -- Run - TestRun : 1 subtask(s) failed
315
+ INFO -- Run - TestRun : Failed
316
+ STR
317
+
318
+ check_status_log run.status_log, [
319
+ {task: 'Run', status: :FAILED, progress: 2, max: 3},
320
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
321
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
322
+ ]
323
+
324
+ check_status_log run.items.first.status_log, [
325
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
326
+ {task: 'ProcessingTask', status: :FAILED, progress: 3, max: 3},
327
+ ]
328
+
329
+ check_status_log run.items.first.items.first.status_log, [
330
+ {task: 'CollectFiles', status: :DONE},
331
+ {task: 'ProcessingTask', status: :FAILED},
332
+ ]
333
+
334
+ end
335
+
336
+ end
337
+
338
+ context 'when stopped with error' do
339
+ let(:processing) {'error'}
340
+
341
+ it 'should not run final task' do
342
+ run
343
+
344
+ check_output logoutput, <<STR
345
+ INFO -- Run - TestRun : Ingest run started.
346
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
347
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
348
+ ERROR -- ProcessingTask - items/test_dir_item.rb : Error processing subitem (1/3): Task failed with WorkflowError exception
349
+ ERROR -- ProcessingTask - items/test_file_item.rb : Error processing subitem (2/3): Task failed with WorkflowError exception
350
+ ERROR -- ProcessingTask - items/test_run.rb : Error processing subitem (3/3): Task failed with WorkflowError exception
351
+ ERROR -- ProcessingTask - items : 3 subitem(s) failed
352
+ ERROR -- ProcessingTask - TestRun : 1 subitem(s) failed
353
+ ERROR -- Run - TestRun : 1 subtask(s) failed
354
+ INFO -- Run - TestRun : Failed
355
+ STR
356
+
357
+ check_status_log run.status_log, [
358
+ {task: 'Run', status: :FAILED, progress: 2, max: 3},
359
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
360
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
361
+ ]
362
+
363
+ check_status_log run.items.first.status_log, [
364
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
365
+ {task: 'ProcessingTask', status: :FAILED, progress: 0, max: 3},
366
+ ]
367
+
368
+ check_status_log run.items.first.items.first.status_log, [
369
+ {task: 'CollectFiles', status: :DONE},
370
+ {task: 'ProcessingTask', status: :FAILED},
371
+ ]
372
+
373
+ end
374
+
375
+ end
376
+
377
+ context 'when stopped with abort' do
378
+ let(:processing) {'abort'}
379
+
380
+ it 'should not run final task' do
381
+ run
382
+
383
+ check_output logoutput, <<STR
384
+ INFO -- Run - TestRun : Ingest run started.
385
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
386
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
387
+ FATAL -- ProcessingTask - items/test_dir_item.rb : Fatal error processing subitem (1/3): Task failed with WorkflowAbort exception
388
+ ERROR -- ProcessingTask - items : 1 subitem(s) failed
389
+ ERROR -- ProcessingTask - TestRun : 1 subitem(s) failed
390
+ ERROR -- Run - TestRun : 1 subtask(s) failed
391
+ INFO -- Run - TestRun : Failed
392
+ STR
393
+
394
+ check_status_log run.status_log, [
395
+ {task: 'Run', status: :FAILED, progress: 2, max: 3},
396
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
397
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
398
+ ]
399
+
400
+ check_status_log run.items.first.status_log, [
401
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
402
+ {task: 'ProcessingTask', status: :FAILED, progress: 0, max: 3},
403
+ ]
404
+
405
+ check_status_log run.items.first.items.first.status_log, [
406
+ {task: 'CollectFiles', status: :DONE},
407
+ {task: 'ProcessingTask', status: :FAILED},
408
+ ]
409
+
410
+ end
411
+
412
+ end
413
+
414
+ end
415
+
416
+ context 'with forcing final task' do
417
+ let(:force_run) {true}
418
+
419
+ context 'when processing successfully' do
420
+ let(:processing) {'success'}
421
+
422
+ it 'should run final task' do
423
+ run
424
+
425
+ check_output logoutput, <<STR
426
+ INFO -- Run - TestRun : Ingest run started.
427
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
428
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
429
+ INFO -- ProcessingTask - TestRun : Task success
430
+ INFO -- ProcessingTask - TestRun : Task success
431
+ INFO -- ProcessingTask - TestRun : Task success
432
+ INFO -- Run - TestRun : Running subtask (3/3): FinalTask
433
+ INFO -- FinalTask - TestRun : Final processing of test_dir_item.rb
434
+ INFO -- FinalTask - TestRun : Final processing of test_file_item.rb
435
+ INFO -- FinalTask - TestRun : Final processing of test_run.rb
436
+ INFO -- Run - TestRun : Done
437
+ STR
438
+
439
+ check_status_log run.status_log, [
440
+ {task: 'Run', status: :DONE, progress: 3, max: 3},
441
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
442
+ {task: 'ProcessingTask', status: :DONE, progress: 1, max: 1},
443
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
444
+ ]
445
+
446
+ check_status_log run.items.first.status_log, [
447
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
448
+ {task: 'ProcessingTask', status: :DONE, progress: 3, max: 3},
449
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
450
+ ]
451
+
452
+ check_status_log run.items.first.items.first.status_log, [
453
+ {task: 'CollectFiles', status: :DONE},
454
+ {task: 'ProcessingTask', status: :DONE},
455
+ {task: 'FinalTask', status: :DONE},
456
+ ]
457
+
458
+ end
459
+
460
+ end
461
+
462
+ context 'when stopped with async_halt' do
463
+ let(:processing) {'async_halt'}
464
+
465
+ it 'should run final task' do
466
+ run
467
+
468
+ check_output logoutput, <<STR
469
+ INFO -- Run - TestRun : Ingest run started.
470
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
471
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
472
+ ERROR -- ProcessingTask - TestRun : Task failed with async_halt status
473
+ ERROR -- ProcessingTask - TestRun : Task failed with async_halt status
474
+ ERROR -- ProcessingTask - TestRun : Task failed with async_halt status
475
+ WARN -- ProcessingTask - items : 3 subitem(s) halted in async process
476
+ WARN -- ProcessingTask - TestRun : 1 subitem(s) halted in async process
477
+ INFO -- Run - TestRun : Running subtask (3/3): FinalTask
478
+ INFO -- FinalTask - TestRun : Final processing of test_dir_item.rb
479
+ INFO -- FinalTask - TestRun : Final processing of test_file_item.rb
480
+ INFO -- FinalTask - TestRun : Final processing of test_run.rb
481
+ WARN -- Run - TestRun : 1 subtask(s) halted in async process
482
+ INFO -- Run - TestRun : Waiting for halted async process
483
+ STR
484
+
485
+ check_status_log run.status_log, [
486
+ {task: 'Run', status: :ASYNC_HALT, progress: 3, max: 3},
487
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
488
+ {task: 'ProcessingTask', status: :ASYNC_HALT, progress: 1, max: 1},
489
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
490
+ ]
491
+
492
+ check_status_log run.items.first.status_log, [
493
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
494
+ {task: 'ProcessingTask', status: :ASYNC_HALT, progress: 3, max: 3},
495
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
496
+ ]
497
+
498
+ check_status_log run.items.first.items.first.status_log, [
499
+ {task: 'CollectFiles', status: :DONE},
500
+ {task: 'ProcessingTask', status: :ASYNC_HALT},
501
+ {task: 'FinalTask', status: :DONE},
502
+ ]
503
+
504
+ end
505
+
506
+ end
507
+
508
+ context 'when stopped with fail' do
509
+ let(:processing) {'fail'}
510
+
511
+ it 'should run final task' do
512
+ run
513
+
514
+ check_output logoutput, <<STR
515
+ INFO -- Run - TestRun : Ingest run started.
516
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
517
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
518
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
519
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
520
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
521
+ ERROR -- ProcessingTask - items : 3 subitem(s) failed
522
+ ERROR -- ProcessingTask - TestRun : 1 subitem(s) failed
523
+ INFO -- Run - TestRun : Running subtask (3/3): FinalTask
524
+ INFO -- FinalTask - TestRun : Final processing of test_dir_item.rb
525
+ INFO -- FinalTask - TestRun : Final processing of test_file_item.rb
526
+ INFO -- FinalTask - TestRun : Final processing of test_run.rb
527
+ ERROR -- Run - TestRun : 1 subtask(s) failed
528
+ INFO -- Run - TestRun : Failed
529
+ STR
530
+ check_status_log run.status_log, [
531
+ {task: 'Run', status: :FAILED, progress: 3, max: 3},
532
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
533
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
534
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
535
+ ]
536
+
537
+ check_status_log run.items.first.status_log, [
538
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
539
+ {task: 'ProcessingTask', status: :FAILED, progress: 3, max: 3},
540
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
541
+ ]
542
+
543
+ check_status_log run.items.first.items.first.status_log, [
544
+ {task: 'CollectFiles', status: :DONE},
545
+ {task: 'ProcessingTask', status: :FAILED},
546
+ {task: 'FinalTask', status: :DONE},
547
+ ]
548
+
549
+ end
550
+
551
+ it 'should run final task during retry' do
552
+ run
553
+
554
+ logoutput.truncate(0)
555
+ run.run :retry
556
+
557
+ check_output logoutput, <<STR
558
+ INFO -- Run - TestRun : Ingest run started.
559
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
560
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
561
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
562
+ ERROR -- ProcessingTask - TestRun : Task failed with failed status
563
+ ERROR -- ProcessingTask - items : 3 subitem(s) failed
564
+ ERROR -- ProcessingTask - TestRun : 1 subitem(s) failed
565
+ INFO -- Run - TestRun : Running subtask (3/3): FinalTask
566
+ INFO -- FinalTask - TestRun : Final processing of test_dir_item.rb
567
+ INFO -- FinalTask - TestRun : Final processing of test_file_item.rb
568
+ INFO -- FinalTask - TestRun : Final processing of test_run.rb
569
+ ERROR -- Run - TestRun : 1 subtask(s) failed
570
+ INFO -- Run - TestRun : Failed
571
+ STR
572
+ check_status_log run.status_log, [
573
+ {task: 'Run', status: :FAILED, progress: 3, max: 3},
574
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
575
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
576
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
577
+ {task: 'Run', status: :FAILED, progress: 3, max: 3},
578
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
579
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
580
+ ]
581
+
582
+ check_status_log run.items.first.status_log, [
583
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
584
+ {task: 'ProcessingTask', status: :FAILED, progress: 3, max: 3},
585
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
586
+ {task: 'ProcessingTask', status: :FAILED, progress: 3, max: 3},
587
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
588
+ ]
589
+
590
+ check_status_log run.items.first.items.first.status_log, [
591
+ {task: 'CollectFiles', status: :DONE},
592
+ {task: 'ProcessingTask', status: :FAILED},
593
+ {task: 'FinalTask', status: :DONE},
594
+ {task: 'ProcessingTask', status: :FAILED},
595
+ {task: 'FinalTask', status: :DONE},
596
+ ]
597
+
598
+ end
599
+
600
+ end
601
+
602
+ context 'when stopped with error' do
603
+ let(:processing) {'error'}
604
+
605
+ it 'should run final task' do
606
+ run
607
+
608
+ check_output logoutput, <<STR
609
+ INFO -- Run - TestRun : Ingest run started.
610
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
611
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
612
+ ERROR -- ProcessingTask - items/test_dir_item.rb : Error processing subitem (1/3): Task failed with WorkflowError exception
613
+ ERROR -- ProcessingTask - items/test_file_item.rb : Error processing subitem (2/3): Task failed with WorkflowError exception
614
+ ERROR -- ProcessingTask - items/test_run.rb : Error processing subitem (3/3): Task failed with WorkflowError exception
615
+ ERROR -- ProcessingTask - items : 3 subitem(s) failed
616
+ ERROR -- ProcessingTask - TestRun : 1 subitem(s) failed
617
+ INFO -- Run - TestRun : Running subtask (3/3): FinalTask
618
+ INFO -- FinalTask - TestRun : Final processing of test_dir_item.rb
619
+ INFO -- FinalTask - TestRun : Final processing of test_file_item.rb
620
+ INFO -- FinalTask - TestRun : Final processing of test_run.rb
621
+ ERROR -- Run - TestRun : 1 subtask(s) failed
622
+ INFO -- Run - TestRun : Failed
623
+ STR
624
+ check_status_log run.status_log, [
625
+ {task: 'Run', status: :FAILED, progress: 3, max: 3},
626
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
627
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
628
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
629
+ ]
630
+
631
+ check_status_log run.items.first.status_log, [
632
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
633
+ {task: 'ProcessingTask', status: :FAILED, progress: 0, max: 3},
634
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
635
+ ]
636
+
637
+ check_status_log run.items.first.items.first.status_log, [
638
+ {task: 'CollectFiles', status: :DONE},
639
+ {task: 'ProcessingTask', status: :FAILED},
640
+ {task: 'FinalTask', status: :DONE},
641
+ ]
642
+
643
+ end
644
+
645
+ end
646
+
647
+ context 'when stopped with abort' do
648
+ let(:processing) {'abort'}
649
+
650
+ it 'should run final task' do
651
+ run
652
+
653
+ check_output logoutput, <<STR
654
+ INFO -- Run - TestRun : Ingest run started.
655
+ INFO -- Run - TestRun : Running subtask (1/3): CollectFiles
656
+ INFO -- Run - TestRun : Running subtask (2/3): ProcessingTask
657
+ FATAL -- ProcessingTask - items/test_dir_item.rb : Fatal error processing subitem (1/3): Task failed with WorkflowAbort exception
658
+ ERROR -- ProcessingTask - items : 1 subitem(s) failed
659
+ ERROR -- ProcessingTask - TestRun : 1 subitem(s) failed
660
+ INFO -- Run - TestRun : Running subtask (3/3): FinalTask
661
+ INFO -- FinalTask - TestRun : Final processing of test_dir_item.rb
662
+ INFO -- FinalTask - TestRun : Final processing of test_file_item.rb
663
+ INFO -- FinalTask - TestRun : Final processing of test_run.rb
664
+ ERROR -- Run - TestRun : 1 subtask(s) failed
665
+ INFO -- Run - TestRun : Failed
666
+ STR
667
+
668
+ check_status_log run.status_log, [
669
+ {task: 'Run', status: :FAILED, progress: 3, max: 3},
670
+ {task: 'CollectFiles', status: :DONE, progress: 1, max: 1},
671
+ {task: 'ProcessingTask', status: :FAILED, progress: 1, max: 1},
672
+ {task: 'FinalTask', status: :DONE, progress: 1, max: 1},
673
+ ]
674
+
675
+ check_status_log run.items.first.status_log, [
676
+ {task: 'CollectFiles', status: :DONE, progress: 3, max: 3},
677
+ {task: 'ProcessingTask', status: :FAILED, progress: 0, max: 3},
678
+ {task: 'FinalTask', status: :DONE, progress: 3, max: 3},
679
+ ]
680
+
681
+ check_status_log run.items.first.items.first.status_log, [
682
+ {task: 'CollectFiles', status: :DONE},
683
+ {task: 'ProcessingTask', status: :FAILED},
684
+ {task: 'FinalTask', status: :DONE},
685
+ ]
686
+
687
+ end
688
+
152
689
  end
153
690
 
154
691
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libis-workflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.36
4
+ version: 2.0.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kris Dekeyser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-09 00:00:00.000000000 Z
11
+ date: 2018-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: awesome_print
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: libis-tools
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -170,6 +184,8 @@ files:
170
184
  - spec/tasks/camelize_name.rb
171
185
  - spec/tasks/checksum_tester.rb
172
186
  - spec/tasks/collect_files.rb
187
+ - spec/tasks/final_task.rb
188
+ - spec/tasks/processing_task.rb
173
189
  - spec/workflow_spec.rb
174
190
  homepage: https://github.com/Kris-LIBIS/workflow
175
191
  licenses:
@@ -205,4 +221,6 @@ test_files:
205
221
  - spec/tasks/camelize_name.rb
206
222
  - spec/tasks/checksum_tester.rb
207
223
  - spec/tasks/collect_files.rb
224
+ - spec/tasks/final_task.rb
225
+ - spec/tasks/processing_task.rb
208
226
  - spec/workflow_spec.rb