libis-workflow 2.0.beta.9 → 2.0.beta.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -13
- data/README.md +190 -94
- data/lib/libis/workflow/base/dir_item.rb +15 -0
- data/lib/libis/workflow/base/file_item.rb +82 -0
- data/lib/libis/workflow/base/run.rb +21 -9
- data/lib/libis/workflow/base/work_item.rb +246 -0
- data/lib/libis/workflow/base/workflow.rb +66 -13
- data/lib/libis/workflow/base.rb +6 -0
- data/lib/libis/workflow/dir_item.rb +12 -0
- data/lib/libis/workflow/file_item.rb +17 -0
- data/lib/libis/workflow/run.rb +3 -4
- data/lib/libis/workflow/task.rb +22 -17
- data/lib/libis/workflow/tasks/analyzer.rb +6 -3
- data/lib/libis/workflow/version.rb +1 -1
- data/lib/libis/workflow/work_item.rb +51 -0
- data/lib/libis/workflow.rb +12 -6
- data/spec/items/test_dir_item.rb +2 -3
- data/spec/items/test_file_item.rb +2 -3
- data/spec/items/test_run.rb +1 -1
- data/spec/tasks/camelize_name.rb +1 -1
- data/spec/tasks/checksum_tester.rb +1 -1
- data/spec/workflow_spec.rb +29 -80
- metadata +10 -7
- data/lib/libis/workflow/workitems/dir_item.rb +0 -12
- data/lib/libis/workflow/workitems/file_item.rb +0 -78
- data/lib/libis/workflow/workitems/work_item.rb +0 -231
- data/lib/libis/workflow/workitems.rb +0 -5
data/spec/tasks/camelize_name.rb
CHANGED
data/spec/workflow_spec.rb
CHANGED
@@ -4,16 +4,17 @@ require 'stringio'
|
|
4
4
|
|
5
5
|
describe 'TestWorkflow' do
|
6
6
|
|
7
|
-
let(:
|
7
|
+
let(:basedir) { File.absolute_path File.join(File.dirname(__FILE__)) }
|
8
|
+
let(:dirname) { File.join(basedir, 'items') }
|
8
9
|
|
9
10
|
let(:logoutput) { StringIO.new }
|
10
11
|
|
11
12
|
let(:workflow) {
|
12
13
|
# noinspection RubyResolve
|
13
14
|
::Libis::Workflow.configure do |cfg|
|
14
|
-
cfg.itemdir =
|
15
|
-
cfg.taskdir = File.join(
|
16
|
-
cfg.workdir = File.join(
|
15
|
+
cfg.itemdir = dirname
|
16
|
+
cfg.taskdir = File.join(basedir, 'tasks')
|
17
|
+
cfg.workdir = File.join(basedir, 'work')
|
17
18
|
cfg.logger = Logger.new logoutput
|
18
19
|
cfg.logger.level = Logger::DEBUG
|
19
20
|
end
|
@@ -25,9 +26,7 @@ describe 'TestWorkflow' do
|
|
25
26
|
tasks: [
|
26
27
|
{class: 'CollectFiles', recursive: true},
|
27
28
|
{
|
28
|
-
name: 'ProcessFiles',
|
29
|
-
subitems: true,
|
30
|
-
recursive: false,
|
29
|
+
name: 'ProcessFiles', subitems: true, recursive: false,
|
31
30
|
tasks: [
|
32
31
|
{class: 'ChecksumTester', recursive: true},
|
33
32
|
{class: 'CamelizeName', recursive: true}
|
@@ -71,54 +70,24 @@ describe 'TestWorkflow' do
|
|
71
70
|
it 'should return expected debug output' do
|
72
71
|
|
73
72
|
sample_out = <<STR
|
74
|
-
DEBUG -- CollectFiles - TestRun : Started
|
75
73
|
DEBUG -- CollectFiles - TestRun : Processing subitem (1/1): items
|
76
|
-
DEBUG -- CollectFiles - items : Started
|
77
74
|
DEBUG -- CollectFiles - items : Processing subitem (1/3): test_dir_item.rb
|
78
|
-
DEBUG -- CollectFiles - items/test_dir_item.rb : Started
|
79
|
-
DEBUG -- CollectFiles - items/test_dir_item.rb : Completed
|
80
75
|
DEBUG -- CollectFiles - items : Processing subitem (2/3): test_file_item.rb
|
81
|
-
DEBUG -- CollectFiles - items/test_file_item.rb : Started
|
82
|
-
DEBUG -- CollectFiles - items/test_file_item.rb : Completed
|
83
76
|
DEBUG -- CollectFiles - items : Processing subitem (3/3): test_run.rb
|
84
|
-
DEBUG -- CollectFiles - items/test_run.rb : Started
|
85
|
-
DEBUG -- CollectFiles - items/test_run.rb : Completed
|
86
77
|
DEBUG -- CollectFiles - items : 3 of 3 subitems passed
|
87
|
-
DEBUG -- CollectFiles - items : Completed
|
88
78
|
DEBUG -- CollectFiles - TestRun : 1 of 1 subitems passed
|
89
|
-
DEBUG -- CollectFiles - TestRun : Completed
|
90
|
-
DEBUG -- ProcessFiles - TestRun : Started
|
91
79
|
DEBUG -- ProcessFiles - TestRun : Processing subitem (1/1): items
|
92
|
-
DEBUG -- ProcessFiles - items : Started
|
93
80
|
DEBUG -- ProcessFiles - items : Running subtask (1/2): ChecksumTester
|
94
|
-
DEBUG -- ProcessFiles/ChecksumTester - items : Started
|
95
81
|
DEBUG -- ProcessFiles/ChecksumTester - items : Processing subitem (1/3): test_dir_item.rb
|
96
|
-
DEBUG -- ProcessFiles/ChecksumTester - items/test_dir_item.rb : Started
|
97
|
-
DEBUG -- ProcessFiles/ChecksumTester - items/test_dir_item.rb : Completed
|
98
82
|
DEBUG -- ProcessFiles/ChecksumTester - items : Processing subitem (2/3): test_file_item.rb
|
99
|
-
DEBUG -- ProcessFiles/ChecksumTester - items/test_file_item.rb : Started
|
100
|
-
DEBUG -- ProcessFiles/ChecksumTester - items/test_file_item.rb : Completed
|
101
83
|
DEBUG -- ProcessFiles/ChecksumTester - items : Processing subitem (3/3): test_run.rb
|
102
|
-
DEBUG -- ProcessFiles/ChecksumTester - items/test_run.rb : Started
|
103
|
-
DEBUG -- ProcessFiles/ChecksumTester - items/test_run.rb : Completed
|
104
84
|
DEBUG -- ProcessFiles/ChecksumTester - items : 3 of 3 subitems passed
|
105
|
-
DEBUG -- ProcessFiles/ChecksumTester - items : Completed
|
106
85
|
DEBUG -- ProcessFiles - items : Running subtask (2/2): CamelizeName
|
107
|
-
DEBUG -- ProcessFiles/CamelizeName - items : Started
|
108
86
|
DEBUG -- ProcessFiles/CamelizeName - Items : Processing subitem (1/3): test_dir_item.rb
|
109
|
-
DEBUG -- ProcessFiles/CamelizeName - Items/test_dir_item.rb : Started
|
110
|
-
DEBUG -- ProcessFiles/CamelizeName - Items/TestDirItem.rb : Completed
|
111
87
|
DEBUG -- ProcessFiles/CamelizeName - Items : Processing subitem (2/3): test_file_item.rb
|
112
|
-
DEBUG -- ProcessFiles/CamelizeName - Items/test_file_item.rb : Started
|
113
|
-
DEBUG -- ProcessFiles/CamelizeName - Items/TestFileItem.rb : Completed
|
114
88
|
DEBUG -- ProcessFiles/CamelizeName - Items : Processing subitem (3/3): test_run.rb
|
115
|
-
DEBUG -- ProcessFiles/CamelizeName - Items/test_run.rb : Started
|
116
|
-
DEBUG -- ProcessFiles/CamelizeName - Items/TestRun.rb : Completed
|
117
89
|
DEBUG -- ProcessFiles/CamelizeName - Items : 3 of 3 subitems passed
|
118
|
-
DEBUG -- ProcessFiles/CamelizeName - Items : Completed
|
119
|
-
DEBUG -- ProcessFiles - Items : Completed
|
120
90
|
DEBUG -- ProcessFiles - TestRun : 1 of 1 subitems passed
|
121
|
-
DEBUG -- ProcessFiles - TestRun : Completed
|
122
91
|
STR
|
123
92
|
sample_out = sample_out.lines.to_a
|
124
93
|
output = logoutput.string.lines.to_a
|
@@ -128,10 +97,10 @@ STR
|
|
128
97
|
expect(o[/(?<=\] ).*/]).to eq sample_out[i].strip
|
129
98
|
end
|
130
99
|
|
131
|
-
expect(run.summary['DEBUG']).to eq
|
132
|
-
expect(run.log_history.count).to eq
|
100
|
+
expect(run.summary['DEBUG']).to eq 18
|
101
|
+
expect(run.log_history.count).to eq 4
|
133
102
|
expect(run.status_log.count).to eq 6
|
134
|
-
expect(run.items.first.log_history.count).to eq
|
103
|
+
expect(run.items.first.log_history.count).to eq 14
|
135
104
|
expect(run.items.first.status_log.count).to eq 8
|
136
105
|
|
137
106
|
[
|
@@ -170,55 +139,35 @@ STR
|
|
170
139
|
end
|
171
140
|
|
172
141
|
[
|
173
|
-
{severity: 'DEBUG', task: 'CollectFiles',
|
174
|
-
{severity: 'DEBUG', task: 'CollectFiles',
|
175
|
-
{severity: 'DEBUG', task: '
|
176
|
-
{severity: 'DEBUG', task: '
|
177
|
-
{severity: 'DEBUG', task: 'ProcessFiles', id: 0, message: 'Started'},
|
178
|
-
{severity: 'DEBUG', task: 'ProcessFiles', id: 0, message: 'Processing subitem (1/1): items'},
|
179
|
-
{severity: 'DEBUG', task: 'ProcessFiles', id: 0, message: '1 of 1 subitems passed'},
|
180
|
-
{severity: 'DEBUG', task: 'ProcessFiles', id: 0, message: 'Completed'},
|
142
|
+
{severity: 'DEBUG', task: 'CollectFiles', message: 'Processing subitem (1/1): items'},
|
143
|
+
{severity: 'DEBUG', task: 'CollectFiles', message: '1 of 1 subitems passed'},
|
144
|
+
{severity: 'DEBUG', task: 'ProcessFiles', message: 'Processing subitem (1/1): items'},
|
145
|
+
{severity: 'DEBUG', task: 'ProcessFiles', message: '1 of 1 subitems passed'},
|
181
146
|
].each_with_index do |h, i|
|
182
147
|
h.keys.each { |key| expect(run.log_history[i][key]).to eq h[key] }
|
183
148
|
end
|
184
149
|
|
185
150
|
[
|
186
|
-
{severity: 'DEBUG', task: 'CollectFiles',
|
187
|
-
{severity: 'DEBUG', task: 'CollectFiles',
|
188
|
-
{severity: 'DEBUG', task: 'CollectFiles',
|
189
|
-
{severity: 'DEBUG', task: 'CollectFiles',
|
190
|
-
{severity: 'DEBUG', task: '
|
191
|
-
{severity: 'DEBUG', task: '
|
192
|
-
{severity: 'DEBUG', task: 'ProcessFiles',
|
193
|
-
{severity: 'DEBUG', task: 'ProcessFiles',
|
194
|
-
{severity: 'DEBUG', task: 'ProcessFiles/ChecksumTester',
|
195
|
-
{severity: 'DEBUG', task: 'ProcessFiles
|
196
|
-
{severity: 'DEBUG', task: 'ProcessFiles/
|
197
|
-
{severity: 'DEBUG', task: 'ProcessFiles/
|
198
|
-
{severity: 'DEBUG', task: 'ProcessFiles/
|
199
|
-
{severity: 'DEBUG', task: 'ProcessFiles/
|
200
|
-
{severity: 'DEBUG', task: 'ProcessFiles', id: 0, message: 'Running subtask (2/2): CamelizeName'},
|
201
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: 'Started'},
|
202
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: 'Processing subitem (1/3): test_dir_item.rb'},
|
203
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: 'Processing subitem (2/3): test_file_item.rb'},
|
204
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: 'Processing subitem (3/3): test_run.rb'},
|
205
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: '3 of 3 subitems passed'},
|
206
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: 'Completed'},
|
207
|
-
{severity: 'DEBUG', task: 'ProcessFiles', id: 0, message: 'Completed'},
|
151
|
+
{severity: 'DEBUG', task: 'CollectFiles', message: 'Processing subitem (1/3): test_dir_item.rb'},
|
152
|
+
{severity: 'DEBUG', task: 'CollectFiles', message: 'Processing subitem (2/3): test_file_item.rb'},
|
153
|
+
{severity: 'DEBUG', task: 'CollectFiles', message: 'Processing subitem (3/3): test_run.rb'},
|
154
|
+
{severity: 'DEBUG', task: 'CollectFiles', message: '3 of 3 subitems passed'},
|
155
|
+
{severity: 'DEBUG', task: 'ProcessFiles', message: 'Running subtask (1/2): ChecksumTester'},
|
156
|
+
{severity: 'DEBUG', task: 'ProcessFiles/ChecksumTester', message: 'Processing subitem (1/3): test_dir_item.rb'},
|
157
|
+
{severity: 'DEBUG', task: 'ProcessFiles/ChecksumTester', message: 'Processing subitem (2/3): test_file_item.rb'},
|
158
|
+
{severity: 'DEBUG', task: 'ProcessFiles/ChecksumTester', message: 'Processing subitem (3/3): test_run.rb'},
|
159
|
+
{severity: 'DEBUG', task: 'ProcessFiles/ChecksumTester', message: '3 of 3 subitems passed'},
|
160
|
+
{severity: 'DEBUG', task: 'ProcessFiles', message: 'Running subtask (2/2): CamelizeName'},
|
161
|
+
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', message: 'Processing subitem (1/3): test_dir_item.rb'},
|
162
|
+
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', message: 'Processing subitem (2/3): test_file_item.rb'},
|
163
|
+
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', message: 'Processing subitem (3/3): test_run.rb'},
|
164
|
+
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', message: '3 of 3 subitems passed'},
|
208
165
|
].each_with_index do |h, i|
|
209
166
|
h.keys.each { |key| expect(run.items.first.log_history[i][key]).to eq h[key] }
|
210
167
|
end
|
211
168
|
|
212
|
-
|
213
|
-
|
214
|
-
{severity: 'DEBUG', task: 'CollectFiles', id: 0, message: 'Completed'},
|
215
|
-
{severity: 'DEBUG', task: 'ProcessFiles/ChecksumTester', id: 0, message: 'Started'},
|
216
|
-
{severity: 'DEBUG', task: 'ProcessFiles/ChecksumTester', id: 0, message: 'Completed'},
|
217
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: 'Started'},
|
218
|
-
{severity: 'DEBUG', task: 'ProcessFiles/CamelizeName', id: 0, message: 'Completed'},
|
219
|
-
].each_with_index do |h, i|
|
220
|
-
h.keys.each { |key| expect(run.items.first.first.log_history[i][key]).to eq h[key] }
|
221
|
-
end
|
169
|
+
# noinspection RubyResolve
|
170
|
+
expect(run.items.first.first.log_history).to be_empty
|
222
171
|
|
223
172
|
end
|
224
173
|
|
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.beta.
|
4
|
+
version: 2.0.beta.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kris Dekeyser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -124,21 +124,24 @@ files:
|
|
124
124
|
- lib/libis-workflow.rb
|
125
125
|
- lib/libis/exceptions.rb
|
126
126
|
- lib/libis/workflow.rb
|
127
|
+
- lib/libis/workflow/base.rb
|
128
|
+
- lib/libis/workflow/base/dir_item.rb
|
129
|
+
- lib/libis/workflow/base/file_item.rb
|
127
130
|
- lib/libis/workflow/base/logger.rb
|
128
131
|
- lib/libis/workflow/base/run.rb
|
132
|
+
- lib/libis/workflow/base/work_item.rb
|
129
133
|
- lib/libis/workflow/base/workflow.rb
|
130
134
|
- lib/libis/workflow/config.rb
|
135
|
+
- lib/libis/workflow/dir_item.rb
|
136
|
+
- lib/libis/workflow/file_item.rb
|
131
137
|
- lib/libis/workflow/message_registry.rb
|
132
138
|
- lib/libis/workflow/run.rb
|
133
139
|
- lib/libis/workflow/task.rb
|
134
140
|
- lib/libis/workflow/tasks/analyzer.rb
|
135
141
|
- lib/libis/workflow/version.rb
|
142
|
+
- lib/libis/workflow/work_item.rb
|
136
143
|
- lib/libis/workflow/worker.rb
|
137
144
|
- lib/libis/workflow/workflow.rb
|
138
|
-
- lib/libis/workflow/workitems.rb
|
139
|
-
- lib/libis/workflow/workitems/dir_item.rb
|
140
|
-
- lib/libis/workflow/workitems/file_item.rb
|
141
|
-
- lib/libis/workflow/workitems/work_item.rb
|
142
145
|
- libis-workflow.gemspec
|
143
146
|
- spec/items.rb
|
144
147
|
- spec/items/test_dir_item.rb
|
@@ -170,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
173
|
version: 1.3.1
|
171
174
|
requirements: []
|
172
175
|
rubyforge_project:
|
173
|
-
rubygems_version: 2.
|
176
|
+
rubygems_version: 2.2.2
|
174
177
|
signing_key:
|
175
178
|
specification_version: 4
|
176
179
|
summary: LIBIS Workflow framework.
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'digest'
|
4
|
-
|
5
|
-
require 'libis/workflow/workitems/work_item'
|
6
|
-
|
7
|
-
module Libis
|
8
|
-
module Workflow
|
9
|
-
|
10
|
-
module FileItem
|
11
|
-
include WorkItem
|
12
|
-
|
13
|
-
def filename
|
14
|
-
File.basename(self.properties[:filename]) || self.properties[:link]
|
15
|
-
end
|
16
|
-
|
17
|
-
def name
|
18
|
-
self.properties[:name] || self.filename
|
19
|
-
end
|
20
|
-
|
21
|
-
def filelist
|
22
|
-
(self.parent.filelist rescue Array.new).push(filename).compact
|
23
|
-
end
|
24
|
-
|
25
|
-
def filepath
|
26
|
-
self.filelist.join('/')
|
27
|
-
end
|
28
|
-
|
29
|
-
def fullpath
|
30
|
-
self.properties[:filename]
|
31
|
-
end
|
32
|
-
|
33
|
-
def filename=(name)
|
34
|
-
begin
|
35
|
-
stats = ::File.stat name
|
36
|
-
self.properties[:size] = stats.size
|
37
|
-
self.properties[:access_time] = stats.atime
|
38
|
-
self.properties[:modification_time] = stats.mtime
|
39
|
-
self.properties[:creation_time] = stats.ctime
|
40
|
-
self.properties[:mode] = stats.mode
|
41
|
-
self.properties[:uid] = stats.uid
|
42
|
-
self.properties[:gid] = stats.gid
|
43
|
-
set_checksum(:MD5, ::Digest::MD5.hexdigest(File.read(name))) if File.file?(name)
|
44
|
-
rescue
|
45
|
-
# ignored
|
46
|
-
end
|
47
|
-
self.properties[:filename] = name
|
48
|
-
end
|
49
|
-
|
50
|
-
def checksum(checksum_type)
|
51
|
-
self.properties[('checksum_' + checksum_type.to_s.downcase).to_sym]
|
52
|
-
end
|
53
|
-
|
54
|
-
def set_checksum(checksum_type, value)
|
55
|
-
self.properties[('checksum_' + checksum_type.to_s.downcase).to_sym] = value
|
56
|
-
end
|
57
|
-
|
58
|
-
def link
|
59
|
-
self.properties[:link]
|
60
|
-
end
|
61
|
-
|
62
|
-
def link=(name)
|
63
|
-
self.properties[:link] = name
|
64
|
-
end
|
65
|
-
|
66
|
-
def set_info(info)
|
67
|
-
info.each do |k, v|
|
68
|
-
self.properties[k] = v
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def safe_name
|
73
|
-
self.name.to_s.gsub(/[^\w.-]/) { |s| '%%%02x' % s.ord }
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,231 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'backports/rails/hash'
|
4
|
-
|
5
|
-
require 'libis/workflow/config'
|
6
|
-
|
7
|
-
module Libis
|
8
|
-
module Workflow
|
9
|
-
|
10
|
-
# Base module for all work items.
|
11
|
-
#
|
12
|
-
# This module contains some basic attributes required for making the workflow and tasks behave properly:
|
13
|
-
#
|
14
|
-
# - status: [Symbol] the status field. Each task sets the status of the items it works on. Before starting processing
|
15
|
-
# the status is set to "#{task_name}Started". After successfull processing it is set to "#{task_name}Done" and if
|
16
|
-
# the task failed, it is set to "#{task_name}Failed". The status field can be used to perform real-time
|
17
|
-
# monitoring, reporting and error-recovery or restart of the ingest.
|
18
|
-
# The initial value for this attribute is :START.
|
19
|
-
# - parent: [Object|nil] a link to a parent work item. Work items can be organized in any hierarchy you think is
|
20
|
-
# relevant for your workflow (e.g. directory[/directory...]/file/line or library/section/book/page). Of course
|
21
|
-
# hierarchies are not mandatory.
|
22
|
-
# - items: [Array] a list of child work items. see above.
|
23
|
-
# - options: [Hash] a set of options for the task chain on how to deal with this work item. This attribute can be
|
24
|
-
# used to fine-tune the behaviour of tasks for a particular work item.
|
25
|
-
# - properties: [Hash] a set of properties, typically collected during the workflow processing and used to store
|
26
|
-
# final or intermediate resulst of tasks. The ::Lias::Ingester::FileItem module uses this attribute to store the
|
27
|
-
# properties (e.g. size, checksum, ...) of the file it represents.
|
28
|
-
# - log_history: [Array] a list of all logging messages collected for this work item. Whenever a task logs a message
|
29
|
-
# it will automatically be registered for the work item that it is processing or for the work item that was
|
30
|
-
# supplied as the first argument.
|
31
|
-
# - status_log: [Array] a list of all status changes the work item went through.
|
32
|
-
# - summary: [Hash] collected statistics about the ingest for the work item and its children. This structure will
|
33
|
-
# be filled in by the included task ::Lias::Ingester::Tasks::Analyzer wich is appended to the workflow by default.
|
34
|
-
#
|
35
|
-
# The module is created so that it is possible to implement an ActiveRecord/Datamapper/... implementation easily.
|
36
|
-
|
37
|
-
module WorkItem
|
38
|
-
include Enumerable
|
39
|
-
|
40
|
-
attr_accessor :parent
|
41
|
-
attr_accessor :items
|
42
|
-
attr_accessor :options, :properties
|
43
|
-
attr_accessor :log_history, :status_log
|
44
|
-
attr_accessor :summary
|
45
|
-
|
46
|
-
# The initializer takes care of properly setting the correct default values for the attributes. A derived class
|
47
|
-
# that wishes to define it's own initializer should take care to call 'super' or make sure it overwrites the
|
48
|
-
# attribute definitions itself. (e.g. in a ActiveRecord implementation)
|
49
|
-
def initialize
|
50
|
-
self.parent = nil
|
51
|
-
self.items = []
|
52
|
-
self.options = {}
|
53
|
-
self.properties = {}
|
54
|
-
self.log_history = []
|
55
|
-
self.status_log = []
|
56
|
-
self.summary = {}
|
57
|
-
end
|
58
|
-
|
59
|
-
# String representation of the identity of the work item.
|
60
|
-
#
|
61
|
-
# You may want to overwrite this method as it tries the :name property or whatever #inspect returns if that
|
62
|
-
# failes. Typically this should return the key value, file name or id number. If that's what your :name property
|
63
|
-
# contains, you're fine.
|
64
|
-
#
|
65
|
-
# @return [String] string identification for this work item.
|
66
|
-
def name
|
67
|
-
self.properties[:name] || self.inspect
|
68
|
-
end
|
69
|
-
|
70
|
-
def to_s; self.name; end
|
71
|
-
|
72
|
-
def names
|
73
|
-
(self.parent.names rescue Array.new).push(name).compact
|
74
|
-
end
|
75
|
-
|
76
|
-
def namepath; self.names.join('/'); end
|
77
|
-
|
78
|
-
# File name save version of the to_s output. The output should be safe to use as a file name to store work item
|
79
|
-
# data. Typical use is when extra file items are created by a task and need to be stored on disk. The default
|
80
|
-
# implementation URL-encodes (%xx) all characters except alphanumeric, '.' and '-'.
|
81
|
-
#
|
82
|
-
# @return [String] file name
|
83
|
-
def to_filename
|
84
|
-
self.to_s.gsub(/[^\w.-]/) { |s| '%%%02x' % s.ord }
|
85
|
-
end
|
86
|
-
|
87
|
-
# Gets the current status of the object.
|
88
|
-
#
|
89
|
-
# @return [Symbol] status code
|
90
|
-
def status
|
91
|
-
s = self.status_log.last
|
92
|
-
status_label((s[:text] rescue nil), (s[:tasklist] rescue nil))
|
93
|
-
end
|
94
|
-
|
95
|
-
# Changes the status of the object. As a side effect the status is also logged in the status_log with the current
|
96
|
-
# timestamp.
|
97
|
-
#
|
98
|
-
# @param [Symbol] s
|
99
|
-
def status=(s, tasklist = nil)
|
100
|
-
s, tasklist = s if s.is_a? Array
|
101
|
-
s = s.to_sym
|
102
|
-
if status_label(s, tasklist) != self.status
|
103
|
-
self.status_log << {
|
104
|
-
timestamp: ::Time.now,
|
105
|
-
tasklist: tasklist,
|
106
|
-
text: s
|
107
|
-
}
|
108
|
-
self.save
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Check ingest status of the object. The status is checked to see if it ends in 'Failed'.
|
113
|
-
#
|
114
|
-
# @return [Boolean] true if the object failed, false otherwise
|
115
|
-
def failed?
|
116
|
-
self.status.to_s =~ /Failed$/ ? true : false
|
117
|
-
end
|
118
|
-
|
119
|
-
# Helper function for the Tasks to add a log entry to the log_history.
|
120
|
-
#
|
121
|
-
# The supplied message structure is expected to contain the following fields:
|
122
|
-
# - :severity : ::Logger::Severity value
|
123
|
-
# - :id : optional message id
|
124
|
-
# - :text : message text
|
125
|
-
# - :task : list of tasks names (task hierarchy) that submits the message
|
126
|
-
#
|
127
|
-
# @param [Hash] message
|
128
|
-
def add_log(message = {})
|
129
|
-
msg = message_struct(message)
|
130
|
-
self.log_history << msg
|
131
|
-
self.save
|
132
|
-
end
|
133
|
-
|
134
|
-
def <=(message = {}); self.add_log(message); end
|
135
|
-
|
136
|
-
# Iterates over the work item clients and invokes code on each of them.
|
137
|
-
def each
|
138
|
-
self.items.each { |item| yield item }
|
139
|
-
end
|
140
|
-
|
141
|
-
# Add a child work item
|
142
|
-
#
|
143
|
-
# @param [WorkItem] item to be added to the child list :items
|
144
|
-
def add_item(item)
|
145
|
-
return self unless item and item.is_a? WorkItem
|
146
|
-
self.items << item
|
147
|
-
item.parent = self
|
148
|
-
self.save!
|
149
|
-
item.save!
|
150
|
-
self
|
151
|
-
end
|
152
|
-
|
153
|
-
alias :<< :add_item
|
154
|
-
|
155
|
-
# Dummy method. It is a placeholder for DB backed implementations. Wherever appropriate WorkItem#save will be
|
156
|
-
# called to save the current item's state. If state needs to persisted, you should override this method or make
|
157
|
-
# sure your persistence layer implements it in your class.
|
158
|
-
def save
|
159
|
-
end
|
160
|
-
|
161
|
-
# Dummy method. It is a placeholder for DB backed implementations. Wherever appropriate WorkItem#save will be
|
162
|
-
# called to save the current item's state. If state needs to persisted, you should override this method or make
|
163
|
-
# sure your persistence layer implements it in your class.
|
164
|
-
def save!
|
165
|
-
end
|
166
|
-
|
167
|
-
# Add a structured message to the log history. The message text can be submitted as an integer or text. If an
|
168
|
-
# integer is submitted, it will be used to look up the text in the MessageRegistry. The message text will be
|
169
|
-
# passed to the % operator with the args parameter. If that failes (e.g. because the format string is not correct)
|
170
|
-
# the args value is appended to the message.
|
171
|
-
#
|
172
|
-
# @param [Symbol] severity
|
173
|
-
# @param [Hash] msg should contain message text as :id or :text and the hierarchical name of the task as :task
|
174
|
-
# @param [Array] args string format values
|
175
|
-
def log_message(severity, msg, *args)
|
176
|
-
# Prepare info from msg struct for use with string substitution
|
177
|
-
message_id, message_text = if msg[:id]
|
178
|
-
[msg[:id], MessageRegistry.instance.get_message(msg[:id])]
|
179
|
-
elsif msg[:text]
|
180
|
-
[0, msg[:text]]
|
181
|
-
else
|
182
|
-
[0, '']
|
183
|
-
end
|
184
|
-
task = msg[:task] || '*UNKNOWN*'
|
185
|
-
message_text = (message_text % args rescue "#{message_text} - #{args}")
|
186
|
-
|
187
|
-
self.add_log severity: severity, id: message_id.to_i, text: message_text, task: task
|
188
|
-
name = ''
|
189
|
-
begin
|
190
|
-
name = self.to_s
|
191
|
-
name = self.name
|
192
|
-
name = self.namepath
|
193
|
-
rescue
|
194
|
-
# do nothing
|
195
|
-
end
|
196
|
-
Config.logger.add(severity, message_text, ('%s - %s ' % [task, name]))
|
197
|
-
end
|
198
|
-
|
199
|
-
protected
|
200
|
-
|
201
|
-
SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY) unless const_defined? :SEV_LABEL
|
202
|
-
|
203
|
-
# go up the hierarchy and return the topmost work item
|
204
|
-
#
|
205
|
-
# @return [WorkItem] the root work item
|
206
|
-
def root
|
207
|
-
root = self
|
208
|
-
root = root.parent while root.parent and root.parent.is_a? WorkItem
|
209
|
-
root
|
210
|
-
end
|
211
|
-
|
212
|
-
# create and return a proper message structure
|
213
|
-
# @param [Hash] opts
|
214
|
-
def message_struct(opts = {})
|
215
|
-
opts.reverse_merge!(severity: ::Logger::INFO, id: 0, text: '')
|
216
|
-
{
|
217
|
-
timestamp: ::Time.now,
|
218
|
-
severity: SEV_LABEL[opts[:severity]],
|
219
|
-
task: opts[:task],
|
220
|
-
id: opts[:id],
|
221
|
-
message: opts[:text]
|
222
|
-
}
|
223
|
-
end
|
224
|
-
|
225
|
-
def status_label(text, tasklist)
|
226
|
-
s = "#{tasklist.last rescue ''}#{text}" rescue :NOT_STARTED
|
227
|
-
s.empty? ? :NOT_STARTED : s.to_sym
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|