libis-workflow 2.0.36 → 2.0.37

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.
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