libis-workflow 2.0.beta.9 → 2.0.beta.10
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 +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
|