taskinator 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +19 -19
- data/lib/taskinator/definition/builder.rb +15 -15
- data/lib/taskinator/definition.rb +2 -2
- data/lib/taskinator/process.rb +10 -13
- data/lib/taskinator/task.rb +13 -16
- data/lib/taskinator/version.rb +1 -1
- data/lib/taskinator.rb +0 -1
- data/spec/examples/process_examples.rb +0 -1
- data/spec/examples/task_examples.rb +0 -1
- data/spec/support/test_flow.rb +17 -17
- data/spec/taskinator/complex_process_spec.rb +0 -2
- data/spec/taskinator/definition/builder_spec.rb +20 -20
- data/spec/taskinator/persistence_spec.rb +3 -3
- data/spec/taskinator/process_spec.rb +23 -19
- data/spec/taskinator/task_spec.rb +20 -16
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0f77cfa37c2c81aeafdfc15dc008d1189a85e14
|
4
|
+
data.tar.gz: 0a297360345128af32a48ce6ff4ffdac386aba01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a65f2d17d83e86d083e3c1343972a46e13a68e693af433290251f2d3aba340a80c13620c8184bd5f644a0d7399435a327ff064afb3e0f0403edef84c8d0611bf
|
7
|
+
data.tar.gz: 132c02957ff6e96fe6ae620685f2168569595bc9becda49e26ed0665403598e0cb08927a962c7a689bea87ab908d72f83ad7d8b45cd677e10a35a103d3a6da71
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -77,8 +77,8 @@ module MyProcess
|
|
77
77
|
extend Taskinator::Definition
|
78
78
|
|
79
79
|
define_process do
|
80
|
-
task
|
81
|
-
task
|
80
|
+
task :first_work_step
|
81
|
+
task :second_work_step
|
82
82
|
end
|
83
83
|
|
84
84
|
def first_work_step
|
@@ -100,14 +100,14 @@ module MyProcess
|
|
100
100
|
define_process do
|
101
101
|
concurrent do
|
102
102
|
# these tasks will be executed concurrently
|
103
|
-
task
|
104
|
-
task
|
103
|
+
task :work_step_1
|
104
|
+
task :work_step_2
|
105
105
|
end
|
106
106
|
|
107
107
|
sequential do
|
108
108
|
# thes tasks will be executed sequentially
|
109
|
-
task
|
110
|
-
task
|
109
|
+
task :work_step_3
|
110
|
+
task :work_step_4
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -134,7 +134,7 @@ module MyProcess
|
|
134
134
|
|
135
135
|
define_process do
|
136
136
|
for_each :yield_data_elements do
|
137
|
-
task
|
137
|
+
task :work_step
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
@@ -164,8 +164,8 @@ module MyProcess
|
|
164
164
|
extend Taskinator::Definition
|
165
165
|
|
166
166
|
define_process do
|
167
|
-
sub_process
|
168
|
-
sub_process
|
167
|
+
sub_process MySubProcessA
|
168
|
+
sub_process MySubProcessB
|
169
169
|
end
|
170
170
|
end
|
171
171
|
```
|
@@ -178,27 +178,28 @@ module MyProcess
|
|
178
178
|
|
179
179
|
define_process do
|
180
180
|
for_each :data_elements do
|
181
|
-
task
|
181
|
+
task :work_step_begin
|
182
182
|
|
183
183
|
concurrent do
|
184
184
|
for_each :sub_data_elements do
|
185
|
-
task
|
185
|
+
task :work_step_all_at_once
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
189
|
-
sub_process
|
189
|
+
sub_process MySubProcess
|
190
190
|
|
191
191
|
sequential do
|
192
192
|
for_each :sub_data_elements do
|
193
|
-
task
|
193
|
+
task :work_step_one_by_one
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
-
task
|
197
|
+
task :work_step_end
|
198
198
|
end
|
199
199
|
end
|
200
200
|
|
201
201
|
# "task" and "iterator" methods omitted for brevity
|
202
|
+
|
202
203
|
end
|
203
204
|
```
|
204
205
|
|
@@ -215,6 +216,10 @@ process = MyProcess.create_process
|
|
215
216
|
process.enqueue!
|
216
217
|
```
|
217
218
|
|
219
|
+
#### Arguments
|
220
|
+
|
221
|
+
_TBD_
|
222
|
+
|
218
223
|
### Monitoring
|
219
224
|
|
220
225
|
To monitor the state of the processes, use the `Taskinator::Api::Processes` class. This is still a work in progress.
|
@@ -224,11 +229,6 @@ processes = Taskinator::Api::Processes.new()
|
|
224
229
|
processes.each do |process|
|
225
230
|
# => output the unique process identifier and current state
|
226
231
|
puts [:process, process.uuid, process.current_state.name]
|
227
|
-
|
228
|
-
process.tasks.each do |task|
|
229
|
-
# => output the task name and current state
|
230
|
-
puts [:task, task.name, task.current_state.name]
|
231
|
-
end
|
232
232
|
end
|
233
233
|
```
|
234
234
|
|
@@ -14,24 +14,24 @@ module Taskinator
|
|
14
14
|
end
|
15
15
|
|
16
16
|
# defines a sub process of tasks which are executed sequentially
|
17
|
-
def sequential(
|
17
|
+
def sequential(options={}, &block)
|
18
18
|
raise ArgumentError, 'block' unless block_given?
|
19
19
|
|
20
|
-
sub_process = Process.define_sequential_process_for(
|
21
|
-
Builder.new(define_sub_process_task(
|
20
|
+
sub_process = Process.define_sequential_process_for(@definition, options)
|
21
|
+
Builder.new(define_sub_process_task(@process, sub_process, options), @definition, @args).instance_eval(&block)
|
22
22
|
end
|
23
23
|
|
24
24
|
# defines a sub process of tasks which are executed concurrently
|
25
|
-
def concurrent(
|
25
|
+
def concurrent(complete_on=CompleteOn::Default, options={}, &block)
|
26
26
|
raise ArgumentError, 'block' unless block_given?
|
27
27
|
|
28
|
-
sub_process = Process.define_concurrent_process_for(
|
29
|
-
Builder.new(define_sub_process_task(
|
28
|
+
sub_process = Process.define_concurrent_process_for(@definition, complete_on, options)
|
29
|
+
Builder.new(define_sub_process_task(@process, sub_process, options), @definition, @args).instance_eval(&block)
|
30
30
|
end
|
31
31
|
|
32
32
|
# dynamically defines tasks, using the given @iterator method
|
33
33
|
# the definition will be evaluated for each yielded item
|
34
|
-
def for_each(
|
34
|
+
def for_each(iterator_method, options={}, &block)
|
35
35
|
raise ArgumentError, 'iterator_method' if iterator_method.nil?
|
36
36
|
raise NoMethodError, iterator_method unless @executor.respond_to?(iterator_method)
|
37
37
|
raise ArgumentError, 'block' unless block_given?
|
@@ -42,37 +42,37 @@ module Taskinator
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# defines a task which executes the given @method
|
45
|
-
def task(
|
45
|
+
def task(method, options={})
|
46
46
|
raise ArgumentError, 'method' if method.nil?
|
47
47
|
raise NoMethodError, method unless @executor.respond_to?(method)
|
48
48
|
|
49
|
-
define_step_task(
|
49
|
+
define_step_task(@process, method, @args, options)
|
50
50
|
end
|
51
51
|
|
52
52
|
# defines a sub process task, for the given @definition
|
53
53
|
# the definition specified must have input compatible arguments
|
54
54
|
# to the current definition
|
55
|
-
def sub_process(
|
55
|
+
def sub_process(definition, options={})
|
56
56
|
raise ArgumentError, 'definition' if definition.nil?
|
57
57
|
raise ArgumentError, "#{definition.name} does not extend the #{Definition.name} module" unless definition.kind_of?(Definition)
|
58
58
|
|
59
59
|
# TODO: decide whether the sub process to dynamically receive arguments
|
60
60
|
|
61
61
|
sub_process = definition.create_process(*@args)
|
62
|
-
Builder.new(define_sub_process_task(
|
62
|
+
Builder.new(define_sub_process_task(@process, sub_process, options), definition, @args)
|
63
63
|
end
|
64
64
|
|
65
65
|
private
|
66
66
|
|
67
|
-
def define_step_task(
|
67
|
+
def define_step_task(process, method, args, options={})
|
68
68
|
define_task(process) {
|
69
|
-
Task.define_step_task(
|
69
|
+
Task.define_step_task(process, method, args, options)
|
70
70
|
}
|
71
71
|
end
|
72
72
|
|
73
|
-
def define_sub_process_task(
|
73
|
+
def define_sub_process_task(process, sub_process, options={})
|
74
74
|
define_task(process) {
|
75
|
-
Task.define_sub_process_task(
|
75
|
+
Task.define_sub_process_task(process, sub_process, options)
|
76
76
|
}
|
77
77
|
sub_process
|
78
78
|
end
|
@@ -3,9 +3,9 @@ module Taskinator
|
|
3
3
|
class UndefinedProcessError < RuntimeError; end
|
4
4
|
|
5
5
|
# defines a process
|
6
|
-
def define_process(
|
6
|
+
def define_process(&block)
|
7
7
|
define_singleton_method :_create_process_ do |*args|
|
8
|
-
process = Process.define_sequential_process_for(
|
8
|
+
process = Process.define_sequential_process_for(self)
|
9
9
|
Builder.new(process, self, args).instance_eval(&block)
|
10
10
|
process.save
|
11
11
|
process
|
data/lib/taskinator/process.rb
CHANGED
@@ -4,12 +4,12 @@ module Taskinator
|
|
4
4
|
include ::Workflow
|
5
5
|
|
6
6
|
class << self
|
7
|
-
def define_sequential_process_for(
|
8
|
-
Process::Sequential.new(
|
7
|
+
def define_sequential_process_for(definition, options={})
|
8
|
+
Process::Sequential.new(definition, options)
|
9
9
|
end
|
10
10
|
|
11
|
-
def define_concurrent_process_for(
|
12
|
-
Process::Concurrent.new(
|
11
|
+
def define_concurrent_process_for(definition, complete_on=CompleteOn::Default, options={})
|
12
|
+
Process::Concurrent.new(definition, complete_on, options)
|
13
13
|
end
|
14
14
|
|
15
15
|
def base_key
|
@@ -18,19 +18,17 @@ module Taskinator
|
|
18
18
|
end
|
19
19
|
|
20
20
|
attr_reader :uuid
|
21
|
-
attr_reader :name
|
22
21
|
attr_reader :definition
|
23
22
|
attr_reader :options
|
24
23
|
|
25
24
|
# in the case of sub process tasks, the containing task
|
26
25
|
attr_accessor :parent
|
27
26
|
|
28
|
-
def initialize(
|
27
|
+
def initialize(definition, options={})
|
29
28
|
raise ArgumentError, 'definition' if definition.nil?
|
30
29
|
raise ArgumentError, "#{definition.name} does not extend the #{Definition.name} module" unless definition.kind_of?(Definition)
|
31
30
|
|
32
31
|
@uuid = SecureRandom.uuid
|
33
|
-
@name = name
|
34
32
|
@definition = definition
|
35
33
|
@options = options
|
36
34
|
end
|
@@ -42,7 +40,6 @@ module Taskinator
|
|
42
40
|
def accept(visitor)
|
43
41
|
visitor.visit_attribute(:uuid)
|
44
42
|
visitor.visit_task_reference(:parent)
|
45
|
-
visitor.visit_attribute(:name)
|
46
43
|
visitor.visit_type(:definition)
|
47
44
|
visitor.visit_tasks(tasks)
|
48
45
|
visitor.visit_args(:options)
|
@@ -53,7 +50,7 @@ module Taskinator
|
|
53
50
|
end
|
54
51
|
|
55
52
|
def to_s
|
56
|
-
"#<#{self.class.name}:#{uuid}
|
53
|
+
"#<#{self.class.name}:#{uuid}>"
|
57
54
|
end
|
58
55
|
|
59
56
|
workflow do
|
@@ -84,11 +81,11 @@ module Taskinator
|
|
84
81
|
state :failed
|
85
82
|
|
86
83
|
on_transition do |from, to, event, *args|
|
87
|
-
Taskinator.logger.debug("PROCESS: #{self.class.name}:#{uuid}
|
84
|
+
Taskinator.logger.debug("PROCESS: #{self.class.name}:#{uuid} :: #{from} => #{to}")
|
88
85
|
end
|
89
86
|
|
90
87
|
on_error do |error, from, to, event, *args|
|
91
|
-
Taskinator.logger.error("PROCESS: #{self.class.name}:#{uuid}
|
88
|
+
Taskinator.logger.error("PROCESS: #{self.class.name}:#{uuid} :: #{error.message}")
|
92
89
|
fail!(error)
|
93
90
|
end
|
94
91
|
end
|
@@ -142,8 +139,8 @@ module Taskinator
|
|
142
139
|
class Concurrent < Process
|
143
140
|
attr_reader :complete_on
|
144
141
|
|
145
|
-
def initialize(
|
146
|
-
super(
|
142
|
+
def initialize(definition, complete_on=CompleteOn::Default, options={})
|
143
|
+
super(definition, options)
|
147
144
|
@complete_on = complete_on
|
148
145
|
end
|
149
146
|
|
data/lib/taskinator/task.rb
CHANGED
@@ -4,12 +4,12 @@ module Taskinator
|
|
4
4
|
include ::Workflow
|
5
5
|
|
6
6
|
class << self
|
7
|
-
def define_step_task(
|
8
|
-
Step.new(
|
7
|
+
def define_step_task(process, method, args, options={})
|
8
|
+
Step.new(process, method, args, options)
|
9
9
|
end
|
10
10
|
|
11
|
-
def define_sub_process_task(
|
12
|
-
SubProcess.new(
|
11
|
+
def define_sub_process_task(process, sub_process, options={})
|
12
|
+
SubProcess.new(process, sub_process, options)
|
13
13
|
end
|
14
14
|
|
15
15
|
def base_key
|
@@ -19,25 +19,22 @@ module Taskinator
|
|
19
19
|
|
20
20
|
attr_reader :process
|
21
21
|
attr_reader :uuid
|
22
|
-
attr_reader :name
|
23
22
|
attr_reader :options
|
24
23
|
|
25
24
|
# the next task in the sequence
|
26
25
|
attr_accessor :next
|
27
26
|
|
28
|
-
def initialize(
|
27
|
+
def initialize(process, options={})
|
29
28
|
raise ArgumentError, 'process' if process.nil? || !process.is_a?(Process)
|
30
29
|
|
31
30
|
@uuid = SecureRandom.uuid
|
32
31
|
@process = process
|
33
|
-
@name = name
|
34
32
|
@options = options
|
35
33
|
end
|
36
34
|
|
37
35
|
def accept(visitor)
|
38
36
|
visitor.visit_attribute(:uuid)
|
39
37
|
visitor.visit_process_reference(:process)
|
40
|
-
visitor.visit_attribute(:name)
|
41
38
|
visitor.visit_task_reference(:next)
|
42
39
|
visitor.visit_args(:options)
|
43
40
|
end
|
@@ -47,7 +44,7 @@ module Taskinator
|
|
47
44
|
end
|
48
45
|
|
49
46
|
def to_s
|
50
|
-
"#<#{self.class.name}:#{uuid}
|
47
|
+
"#<#{self.class.name}:#{uuid}>"
|
51
48
|
end
|
52
49
|
|
53
50
|
workflow do
|
@@ -69,16 +66,16 @@ module Taskinator
|
|
69
66
|
state :failed
|
70
67
|
|
71
68
|
on_transition do |from, to, event, *args|
|
72
|
-
Taskinator.logger.debug("TASK: #{self.class.name}:#{uuid}
|
69
|
+
Taskinator.logger.debug("TASK: #{self.class.name}:#{uuid} :: #{from} => #{to}")
|
73
70
|
end
|
74
71
|
|
75
72
|
on_error do |error, from, to, event, *args|
|
76
|
-
Taskinator.logger.error("TASK: #{self.class.name}:#{uuid}
|
73
|
+
Taskinator.logger.error("TASK: #{self.class.name}:#{uuid} :: #{error.message}")
|
77
74
|
fail!(error)
|
78
75
|
end
|
79
76
|
end
|
80
77
|
|
81
|
-
def can_complete_task?
|
78
|
+
def can_complete_task?(*args)
|
82
79
|
# subclasses must implement this method
|
83
80
|
raise NotImplementedError
|
84
81
|
end
|
@@ -115,8 +112,8 @@ module Taskinator
|
|
115
112
|
attr_reader :method
|
116
113
|
attr_reader :args
|
117
114
|
|
118
|
-
def initialize(
|
119
|
-
super(
|
115
|
+
def initialize(process, method, args, options={})
|
116
|
+
super(process, options)
|
120
117
|
@definition = process.definition # for convenience
|
121
118
|
|
122
119
|
raise ArgumentError, 'method' if method.nil?
|
@@ -153,8 +150,8 @@ module Taskinator
|
|
153
150
|
class SubProcess < Task
|
154
151
|
attr_reader :sub_process
|
155
152
|
|
156
|
-
def initialize(
|
157
|
-
super(
|
153
|
+
def initialize(process, sub_process, options={})
|
154
|
+
super(process, options)
|
158
155
|
raise ArgumentError, 'sub_process' if sub_process.nil? || !sub_process.is_a?(Process)
|
159
156
|
|
160
157
|
@sub_process = sub_process
|
data/lib/taskinator/version.rb
CHANGED
data/lib/taskinator.rb
CHANGED
@@ -9,7 +9,6 @@ shared_examples_for "a process" do |process_type|
|
|
9
9
|
|
10
10
|
it { expect(process.definition).to eq(definition) }
|
11
11
|
it { expect(process.uuid).to_not be_nil }
|
12
|
-
it { expect(process.name).to eq('name') }
|
13
12
|
it { expect(process.to_s).to match(/#{process.uuid}/) }
|
14
13
|
it { expect(process.options).to_not be_nil }
|
15
14
|
it { expect(process.tasks).to_not be_nil }
|
@@ -9,7 +9,6 @@ shared_examples_for "a task" do |task_type|
|
|
9
9
|
|
10
10
|
it { expect(task.process).to eq(process) }
|
11
11
|
it { expect(task.uuid).to_not be_nil }
|
12
|
-
it { expect(task.name).to eq('name') }
|
13
12
|
it { expect(task.to_s).to match(/#{task.uuid}/) }
|
14
13
|
it { expect(task.options).to_not be_nil }
|
15
14
|
|
data/spec/support/test_flow.rb
CHANGED
@@ -2,33 +2,33 @@ module TestFlow
|
|
2
2
|
extend Taskinator::Definition
|
3
3
|
|
4
4
|
define_process do
|
5
|
-
task
|
5
|
+
task :error_task, :continue_on_error => true
|
6
6
|
|
7
|
-
task
|
7
|
+
task :the_task
|
8
8
|
|
9
|
-
for_each
|
10
|
-
task
|
9
|
+
for_each :iterator do
|
10
|
+
task :the_task
|
11
11
|
end
|
12
12
|
|
13
|
-
sequential
|
14
|
-
task
|
15
|
-
task
|
16
|
-
task
|
13
|
+
sequential do
|
14
|
+
task :the_task
|
15
|
+
task :the_task
|
16
|
+
task :the_task
|
17
17
|
end
|
18
18
|
|
19
|
-
task
|
19
|
+
task :the_task
|
20
20
|
|
21
|
-
concurrent
|
21
|
+
concurrent do
|
22
22
|
20.times do |i|
|
23
|
-
task
|
23
|
+
task :the_task
|
24
24
|
end
|
25
|
-
task
|
25
|
+
task :the_task
|
26
26
|
end
|
27
27
|
|
28
|
-
task
|
28
|
+
task :the_task
|
29
29
|
|
30
30
|
# invoke the specified sub process
|
31
|
-
sub_process
|
31
|
+
sub_process TestSubFlow
|
32
32
|
end
|
33
33
|
|
34
34
|
def error_task(*args)
|
@@ -53,9 +53,9 @@ module TestFlow
|
|
53
53
|
extend Taskinator::Definition
|
54
54
|
|
55
55
|
define_process do
|
56
|
-
task
|
57
|
-
task
|
58
|
-
task
|
56
|
+
task :the_task
|
57
|
+
task :the_task
|
58
|
+
task :the_task
|
59
59
|
end
|
60
60
|
|
61
61
|
def the_task(*args)
|
@@ -7,7 +7,6 @@ describe TestFlow, :redis => true do
|
|
7
7
|
processB = Taskinator::Process.fetch(processA.uuid)
|
8
8
|
|
9
9
|
expect(processB.uuid).to eq(processA.uuid)
|
10
|
-
expect(processB.name).to eq(processA.name)
|
11
10
|
expect(processB.definition).to eq(processA.definition)
|
12
11
|
expect(processB.options).to eq(processA.options)
|
13
12
|
|
@@ -18,7 +17,6 @@ describe TestFlow, :redis => true do
|
|
18
17
|
tasks.each do |(taskB, taskA)|
|
19
18
|
expect(taskA.process).to eq(taskB.process)
|
20
19
|
expect(taskA.uuid).to eq(taskB.uuid)
|
21
|
-
expect(taskA.name).to eq(taskB.name)
|
22
20
|
expect(taskA.options).to eq(taskB.options)
|
23
21
|
end
|
24
22
|
end
|
@@ -12,7 +12,7 @@ describe Taskinator::Definition::Builder do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
let(:process) {
|
15
|
-
Class.new(Taskinator::Process).new(
|
15
|
+
Class.new(Taskinator::Process).new(definition)
|
16
16
|
}
|
17
17
|
|
18
18
|
let(:args) { [:arg1, :arg2] }
|
@@ -35,18 +35,18 @@ describe Taskinator::Definition::Builder do
|
|
35
35
|
describe "#sequential" do
|
36
36
|
it "invokes supplied block" do
|
37
37
|
expect(block).to receive(:call)
|
38
|
-
subject.sequential(
|
38
|
+
subject.sequential(&define_block)
|
39
39
|
end
|
40
40
|
|
41
41
|
it "creates a sequential process" do
|
42
42
|
allow(block).to receive(:call)
|
43
|
-
expect(Taskinator::Process).to receive(:define_sequential_process_for).with(
|
44
|
-
subject.sequential(
|
43
|
+
expect(Taskinator::Process).to receive(:define_sequential_process_for).with(definition, {}).and_call_original
|
44
|
+
subject.sequential(&define_block)
|
45
45
|
end
|
46
46
|
|
47
47
|
it "fails if block isn't given" do
|
48
48
|
expect {
|
49
|
-
subject.sequential(
|
49
|
+
subject.sequential()
|
50
50
|
}.to raise_error(ArgumentError)
|
51
51
|
end
|
52
52
|
end
|
@@ -54,18 +54,18 @@ describe Taskinator::Definition::Builder do
|
|
54
54
|
describe "#concurrent" do
|
55
55
|
it "invokes supplied block" do
|
56
56
|
expect(block).to receive(:call)
|
57
|
-
subject.concurrent(
|
57
|
+
subject.concurrent(&define_block)
|
58
58
|
end
|
59
59
|
|
60
60
|
it "creates a concurrent process" do
|
61
61
|
allow(block).to receive(:call)
|
62
|
-
expect(Taskinator::Process).to receive(:define_concurrent_process_for).with(
|
63
|
-
subject.concurrent(
|
62
|
+
expect(Taskinator::Process).to receive(:define_concurrent_process_for).with(definition, Taskinator::CompleteOn::First, {}).and_call_original
|
63
|
+
subject.concurrent(Taskinator::CompleteOn::First, &define_block)
|
64
64
|
end
|
65
65
|
|
66
66
|
it "fails if block isn't given" do
|
67
67
|
expect {
|
68
|
-
subject.concurrent(
|
68
|
+
subject.concurrent()
|
69
69
|
}.to raise_error(ArgumentError)
|
70
70
|
end
|
71
71
|
end
|
@@ -87,43 +87,43 @@ describe Taskinator::Definition::Builder do
|
|
87
87
|
|
88
88
|
expect(block).to receive(:call).exactly(3).times
|
89
89
|
|
90
|
-
subject.for_each(
|
90
|
+
subject.for_each(:iterator_method, &define_block)
|
91
91
|
end
|
92
92
|
|
93
93
|
it "fails if iterator method is nil" do
|
94
94
|
expect {
|
95
|
-
subject.for_each(
|
95
|
+
subject.for_each(nil, &define_block)
|
96
96
|
}.to raise_error(ArgumentError)
|
97
97
|
end
|
98
98
|
|
99
99
|
it "fails if iterator method is not defined" do
|
100
100
|
expect {
|
101
|
-
subject.for_each(
|
101
|
+
subject.for_each(:undefined_iterator, &define_block)
|
102
102
|
}.to raise_error(NoMethodError)
|
103
103
|
end
|
104
104
|
|
105
105
|
it "fails if block isn't given" do
|
106
106
|
expect {
|
107
|
-
subject.for_each(
|
107
|
+
subject.for_each(nil)
|
108
108
|
}.to raise_error(ArgumentError)
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
112
|
describe "#task" do
|
113
113
|
it "creates a task" do
|
114
|
-
expect(Taskinator::Task).to receive(:define_step_task).with(
|
115
|
-
subject.task(
|
114
|
+
expect(Taskinator::Task).to receive(:define_step_task).with(process, :task_method, args, {})
|
115
|
+
subject.task(:task_method)
|
116
116
|
end
|
117
117
|
|
118
118
|
it "fails if task method is nil" do
|
119
119
|
expect {
|
120
|
-
subject.task(
|
120
|
+
subject.task(nil)
|
121
121
|
}.to raise_error(ArgumentError)
|
122
122
|
end
|
123
123
|
|
124
124
|
it "fails if task method is not defined" do
|
125
125
|
expect {
|
126
|
-
subject.task(
|
126
|
+
subject.task(:undefined_method)
|
127
127
|
}.to raise_error(NoMethodError)
|
128
128
|
end
|
129
129
|
end
|
@@ -139,14 +139,14 @@ describe Taskinator::Definition::Builder do
|
|
139
139
|
|
140
140
|
it "creates a sub process" do
|
141
141
|
expect(sub_definition).to receive(:create_process).with(*args).and_call_original
|
142
|
-
subject.sub_process(
|
142
|
+
subject.sub_process(sub_definition)
|
143
143
|
end
|
144
144
|
|
145
145
|
it "creates a sub process task" do
|
146
146
|
sub_process = sub_definition.create_process(:argX, :argY)
|
147
147
|
allow(sub_definition).to receive(:create_process) { sub_process }
|
148
|
-
expect(Taskinator::Task).to receive(:define_sub_process_task).with(
|
149
|
-
subject.sub_process(
|
148
|
+
expect(Taskinator::Task).to receive(:define_sub_process_task).with(process, sub_process, {})
|
149
|
+
subject.sub_process(sub_definition)
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -75,7 +75,7 @@ describe Taskinator::Persistence, :redis => true do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
describe "for processes" do
|
78
|
-
let(:process) { TestProcess.new(
|
78
|
+
let(:process) { TestProcess.new(definition) }
|
79
79
|
|
80
80
|
it {
|
81
81
|
process.save
|
@@ -84,8 +84,8 @@ describe Taskinator::Persistence, :redis => true do
|
|
84
84
|
end
|
85
85
|
|
86
86
|
describe "for tasks" do
|
87
|
-
let(:process) { TestProcess.new(
|
88
|
-
let(:task) { TestTask.new(
|
87
|
+
let(:process) { TestProcess.new(definition) }
|
88
|
+
let(:task) { TestTask.new(process) }
|
89
89
|
|
90
90
|
it {
|
91
91
|
process.tasks << task
|
@@ -10,11 +10,10 @@ describe Taskinator::Process do
|
|
10
10
|
|
11
11
|
describe "Base" do
|
12
12
|
|
13
|
-
subject { Class.new(Taskinator::Process).new(
|
13
|
+
subject { Class.new(Taskinator::Process).new(definition) }
|
14
14
|
|
15
15
|
describe "#initialize" do
|
16
16
|
it { expect(subject.uuid).to_not be_nil }
|
17
|
-
it { expect(subject.name).to_not be_nil }
|
18
17
|
it { expect(subject.definition).to_not be_nil }
|
19
18
|
it { expect(subject.definition).to eq(definition) }
|
20
19
|
it { expect(subject.options).to_not be_nil }
|
@@ -46,6 +45,14 @@ describe Taskinator::Process do
|
|
46
45
|
it { expect(subject.current_state.name).to eq(:initial) }
|
47
46
|
end
|
48
47
|
|
48
|
+
describe "#tasks_completed?" do
|
49
|
+
it {
|
50
|
+
expect {
|
51
|
+
subject.tasks_completed?
|
52
|
+
}.to raise_error(NotImplementedError)
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
49
56
|
describe "workflow" do
|
50
57
|
describe "#enqueue!" do
|
51
58
|
it { expect(subject).to respond_to(:enqueue!) }
|
@@ -166,7 +173,6 @@ describe Taskinator::Process do
|
|
166
173
|
visitor = double('visitor')
|
167
174
|
expect(visitor).to receive(:visit_type).with(:definition)
|
168
175
|
expect(visitor).to receive(:visit_attribute).with(:uuid)
|
169
|
-
expect(visitor).to receive(:visit_attribute).with(:name)
|
170
176
|
expect(visitor).to receive(:visit_args).with(:options)
|
171
177
|
expect(visitor).to receive(:visit_task_reference).with(:parent)
|
172
178
|
expect(visitor).to receive(:visit_tasks)
|
@@ -179,28 +185,28 @@ describe Taskinator::Process do
|
|
179
185
|
describe Taskinator::Process::Sequential do
|
180
186
|
|
181
187
|
it_should_behave_like "a process", Taskinator::Process::Sequential do
|
182
|
-
let(:process) { Taskinator::Process.define_sequential_process_for(
|
188
|
+
let(:process) { Taskinator::Process.define_sequential_process_for(definition) }
|
183
189
|
end
|
184
190
|
|
185
|
-
subject { Taskinator::Process.define_sequential_process_for(
|
191
|
+
subject { Taskinator::Process.define_sequential_process_for(definition) }
|
186
192
|
|
187
193
|
let(:tasks) {
|
188
194
|
[
|
189
|
-
Class.new(Taskinator::Task).new(
|
190
|
-
Class.new(Taskinator::Task).new(
|
195
|
+
Class.new(Taskinator::Task).new(subject),
|
196
|
+
Class.new(Taskinator::Task).new(subject)
|
191
197
|
]
|
192
198
|
}
|
193
199
|
|
194
200
|
describe ".define_sequential_process_for" do
|
195
201
|
it "raise error for nil definition" do
|
196
202
|
expect {
|
197
|
-
Taskinator::Process.define_sequential_process_for(
|
203
|
+
Taskinator::Process.define_sequential_process_for(nil)
|
198
204
|
}.to raise_error(ArgumentError)
|
199
205
|
end
|
200
206
|
|
201
207
|
it "raise error for invalid definition" do
|
202
208
|
expect {
|
203
|
-
Taskinator::Process.define_sequential_process_for(
|
209
|
+
Taskinator::Process.define_sequential_process_for(Object)
|
204
210
|
}.to raise_error(ArgumentError)
|
205
211
|
end
|
206
212
|
end
|
@@ -274,7 +280,6 @@ describe Taskinator::Process do
|
|
274
280
|
visitor = double('visitor')
|
275
281
|
expect(visitor).to receive(:visit_type).with(:definition)
|
276
282
|
expect(visitor).to receive(:visit_attribute).with(:uuid)
|
277
|
-
expect(visitor).to receive(:visit_attribute).with(:name)
|
278
283
|
expect(visitor).to receive(:visit_args).with(:options)
|
279
284
|
expect(visitor).to receive(:visit_task_reference).with(:parent)
|
280
285
|
expect(visitor).to receive(:visit_tasks)
|
@@ -286,30 +291,30 @@ describe Taskinator::Process do
|
|
286
291
|
|
287
292
|
describe Taskinator::Process::Concurrent do
|
288
293
|
it_should_behave_like "a process", Taskinator::Process::Concurrent do
|
289
|
-
let(:process) { Taskinator::Process.define_concurrent_process_for(
|
294
|
+
let(:process) { Taskinator::Process.define_concurrent_process_for(definition, Taskinator::CompleteOn::First) }
|
290
295
|
|
291
296
|
it { expect(process.complete_on).to eq(Taskinator::CompleteOn::First) }
|
292
297
|
end
|
293
298
|
|
294
|
-
subject { Taskinator::Process.define_concurrent_process_for(
|
299
|
+
subject { Taskinator::Process.define_concurrent_process_for(definition) }
|
295
300
|
|
296
301
|
let(:tasks) {
|
297
302
|
[
|
298
|
-
Class.new(Taskinator::Task).new(
|
299
|
-
Class.new(Taskinator::Task).new(
|
303
|
+
Class.new(Taskinator::Task).new(subject),
|
304
|
+
Class.new(Taskinator::Task).new(subject)
|
300
305
|
]
|
301
306
|
}
|
302
307
|
|
303
308
|
describe ".define_concurrent_process_for" do
|
304
309
|
it "raise error for nil definition" do
|
305
310
|
expect {
|
306
|
-
Taskinator::Process.define_concurrent_process_for(
|
311
|
+
Taskinator::Process.define_concurrent_process_for(nil)
|
307
312
|
}.to raise_error(ArgumentError)
|
308
313
|
end
|
309
314
|
|
310
315
|
it "raise error for invalid definition" do
|
311
316
|
expect {
|
312
|
-
Taskinator::Process.define_concurrent_process_for(
|
317
|
+
Taskinator::Process.define_concurrent_process_for(Object)
|
313
318
|
}.to raise_error(ArgumentError)
|
314
319
|
end
|
315
320
|
end
|
@@ -344,7 +349,7 @@ describe Taskinator::Process do
|
|
344
349
|
describe "#tasks_completed?" do
|
345
350
|
|
346
351
|
describe "complete on first" do
|
347
|
-
let(:process) { Taskinator::Process.define_concurrent_process_for(
|
352
|
+
let(:process) { Taskinator::Process.define_concurrent_process_for(definition, Taskinator::CompleteOn::First) }
|
348
353
|
|
349
354
|
it "yields false when no tasks have completed" do
|
350
355
|
tasks.each {|t| process.tasks << t }
|
@@ -363,7 +368,7 @@ describe Taskinator::Process do
|
|
363
368
|
end
|
364
369
|
|
365
370
|
describe "complete on last" do
|
366
|
-
let(:process) { Taskinator::Process.define_concurrent_process_for(
|
371
|
+
let(:process) { Taskinator::Process.define_concurrent_process_for(definition, Taskinator::CompleteOn::Last) }
|
367
372
|
|
368
373
|
it "yields false when no tasks have completed" do
|
369
374
|
tasks.each {|t| process.tasks << t }
|
@@ -401,7 +406,6 @@ describe Taskinator::Process do
|
|
401
406
|
visitor = double('visitor')
|
402
407
|
expect(visitor).to receive(:visit_type).with(:definition)
|
403
408
|
expect(visitor).to receive(:visit_attribute).with(:uuid)
|
404
|
-
expect(visitor).to receive(:visit_attribute).with(:name)
|
405
409
|
expect(visitor).to receive(:visit_attribute).with(:complete_on)
|
406
410
|
expect(visitor).to receive(:visit_args).with(:options)
|
407
411
|
expect(visitor).to receive(:visit_task_reference).with(:parent)
|
@@ -10,14 +10,13 @@ describe Taskinator::Task do
|
|
10
10
|
|
11
11
|
describe "Base" do
|
12
12
|
|
13
|
-
let(:process) { Class.new(Taskinator::Process).new(
|
14
|
-
subject { Class.new(Taskinator::Task).new(
|
13
|
+
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
14
|
+
subject { Class.new(Taskinator::Task).new(process) }
|
15
15
|
|
16
16
|
describe "#initialize" do
|
17
17
|
it { expect(subject.process).to_not be_nil }
|
18
18
|
it { expect(subject.process).to eq(process) }
|
19
19
|
it { expect(subject.uuid).to_not be_nil }
|
20
|
-
it { expect(subject.name).to_not be_nil }
|
21
20
|
it { expect(subject.options).to_not be_nil }
|
22
21
|
end
|
23
22
|
|
@@ -43,6 +42,14 @@ describe Taskinator::Task do
|
|
43
42
|
it { expect(subject.current_state.name).to eq(:initial) }
|
44
43
|
end
|
45
44
|
|
45
|
+
describe "#can_complete_task?" do
|
46
|
+
it {
|
47
|
+
expect {
|
48
|
+
subject.can_complete_task?
|
49
|
+
}.to raise_error(NotImplementedError)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
46
53
|
describe "workflow" do
|
47
54
|
describe "#enqueue!" do
|
48
55
|
it { expect(subject).to respond_to(:enqueue!) }
|
@@ -128,7 +135,6 @@ describe Taskinator::Task do
|
|
128
135
|
it {
|
129
136
|
visitor = double('visitor')
|
130
137
|
expect(visitor).to receive(:visit_attribute).with(:uuid)
|
131
|
-
expect(visitor).to receive(:visit_attribute).with(:name)
|
132
138
|
expect(visitor).to receive(:visit_process_reference).with(:process)
|
133
139
|
expect(visitor).to receive(:visit_task_reference).with(:next)
|
134
140
|
expect(visitor).to receive(:visit_args).with(:options)
|
@@ -140,12 +146,12 @@ describe Taskinator::Task do
|
|
140
146
|
|
141
147
|
describe Taskinator::Task::Step do
|
142
148
|
it_should_behave_like "a task", Taskinator::Task::Step do
|
143
|
-
let(:process) { Class.new(Taskinator::Process).new(
|
144
|
-
let(:task) { Taskinator::Task.define_step_task(
|
149
|
+
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
150
|
+
let(:task) { Taskinator::Task.define_step_task(process, :method, {:a => 1, :b => 2}) }
|
145
151
|
end
|
146
152
|
|
147
|
-
let(:process) { Class.new(Taskinator::Process).new(
|
148
|
-
subject { Taskinator::Task.define_step_task(
|
153
|
+
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
154
|
+
subject { Taskinator::Task.define_step_task(process, :method, {:a => 1, :b => 2}) }
|
149
155
|
|
150
156
|
describe "#executor" do
|
151
157
|
it { expect(subject.executor).to_not be_nil }
|
@@ -184,7 +190,6 @@ describe Taskinator::Task do
|
|
184
190
|
visitor = double('visitor')
|
185
191
|
expect(visitor).to receive(:visit_type).with(:definition)
|
186
192
|
expect(visitor).to receive(:visit_attribute).with(:uuid)
|
187
|
-
expect(visitor).to receive(:visit_attribute).with(:name)
|
188
193
|
expect(visitor).to receive(:visit_process_reference).with(:process)
|
189
194
|
expect(visitor).to receive(:visit_task_reference).with(:next)
|
190
195
|
expect(visitor).to receive(:visit_args).with(:options)
|
@@ -198,14 +203,14 @@ describe Taskinator::Task do
|
|
198
203
|
|
199
204
|
describe Taskinator::Task::SubProcess do
|
200
205
|
it_should_behave_like "a task", Taskinator::Task::SubProcess do
|
201
|
-
let(:process) { Class.new(Taskinator::Process).new(
|
202
|
-
let(:sub_process) { Class.new(Taskinator::Process).new(
|
203
|
-
let(:task) { Taskinator::Task.define_sub_process_task(
|
206
|
+
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
207
|
+
let(:sub_process) { Class.new(Taskinator::Process).new(definition) }
|
208
|
+
let(:task) { Taskinator::Task.define_sub_process_task(process, sub_process) }
|
204
209
|
end
|
205
210
|
|
206
|
-
let(:process) { Class.new(Taskinator::Process).new(
|
207
|
-
let(:sub_process) { Class.new(Taskinator::Process).new(
|
208
|
-
subject { Taskinator::Task.define_sub_process_task(
|
211
|
+
let(:process) { Class.new(Taskinator::Process).new(definition) }
|
212
|
+
let(:sub_process) { Class.new(Taskinator::Process).new(definition) }
|
213
|
+
subject { Taskinator::Task.define_sub_process_task(process, sub_process) }
|
209
214
|
|
210
215
|
describe "#start!" do
|
211
216
|
it "delegates to sub process" do
|
@@ -236,7 +241,6 @@ describe Taskinator::Task do
|
|
236
241
|
it {
|
237
242
|
visitor = double('visitor')
|
238
243
|
expect(visitor).to receive(:visit_attribute).with(:uuid)
|
239
|
-
expect(visitor).to receive(:visit_attribute).with(:name)
|
240
244
|
expect(visitor).to receive(:visit_process_reference).with(:process)
|
241
245
|
expect(visitor).to receive(:visit_task_reference).with(:next)
|
242
246
|
expect(visitor).to receive(:visit_args).with(:options)
|