taskinator 0.3.13 → 0.4.1
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 +5 -5
- data/.ruby-version +1 -1
- data/.travis.yml +7 -5
- data/CHANGELOG.md +53 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +82 -77
- data/README.md +0 -1
- data/lib/taskinator.rb +0 -1
- data/lib/taskinator/definition/builder.rb +16 -7
- data/lib/taskinator/process.rb +6 -3
- data/lib/taskinator/task.rb +3 -3
- data/lib/taskinator/version.rb +1 -1
- data/spec/taskinator/definition/builder_spec.rb +48 -0
- data/spec/taskinator/process_spec.rb +151 -1
- data/spec/taskinator/task_spec.rb +32 -8
- data/taskinator.gemspec +3 -2
- metadata +19 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4a5f5f63478b9c1b1419e33baf6039f8e92153638ba2c08dc60cadd1a968d117
|
|
4
|
+
data.tar.gz: e222c79a85490ec2cbced43833b05b40e97dc6863782586505b19b178e44f664
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ffd5ee0e0b9bfc78e9f44086d2b60986483c4668acf9b9a282ed3110d15d59477fec68b1042876d52899fe2531648ccd793efa9ba92415231ad4e637922b8049
|
|
7
|
+
data.tar.gz: 99fb91f000e510dd98eda1d843e644c563ca71288759e7d23493a605b7f7b342a116cff2d2bd530250fb552cd88d728a67171fafb49419461baa7200355d9e47
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-2.
|
|
1
|
+
ruby-2.7.2
|
data/.travis.yml
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
os: linux
|
|
2
|
+
dist: xenial
|
|
1
3
|
language: ruby
|
|
2
|
-
sudo: false # See http://docs.travis-ci.com/user/migrating-from-legacy
|
|
3
4
|
cache: bundler
|
|
4
5
|
|
|
5
6
|
services:
|
|
6
|
-
- redis
|
|
7
|
+
- redis
|
|
7
8
|
|
|
8
9
|
rvm:
|
|
9
|
-
- 2.
|
|
10
|
-
- 2.
|
|
11
|
-
- 2.
|
|
10
|
+
- 2.5.8
|
|
11
|
+
- 2.6.6
|
|
12
|
+
- 2.7.2
|
|
13
|
+
- 3.0.0
|
|
12
14
|
|
|
13
15
|
script: 'bundle exec rake spec'
|
|
14
16
|
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,56 @@
|
|
|
1
|
+
v0.4.1 - 15 Mar 2021
|
|
2
|
+
---
|
|
3
|
+
Optimisation to exclude sub-processes which don't have any tasks.
|
|
4
|
+
Preparations for upgrade to Ruby 3 and ActiveSupport 6
|
|
5
|
+
|
|
6
|
+
v0.4.0 - 4 Mar 2021
|
|
7
|
+
---
|
|
8
|
+
Bug fix `job` tasks which have no arguments to the `perform` method.
|
|
9
|
+
Added support for having `perform` method as a class method.
|
|
10
|
+
|
|
11
|
+
v0.3.16 - 17 Feb 2021
|
|
12
|
+
---
|
|
13
|
+
Bug fix to deincrement pending counts for sequential tasks.
|
|
14
|
+
Bug fix to allow concurrent tasks to be retried (via Resque) and to complete processes.
|
|
15
|
+
|
|
16
|
+
v0.3.15 - 22 Nov 2018
|
|
17
|
+
---
|
|
18
|
+
Updated dependencies.
|
|
19
|
+
|
|
20
|
+
v0.3.14 - 13 Jul 2018
|
|
21
|
+
---
|
|
22
|
+
Updated dependencies.
|
|
23
|
+
Removed gemnasium.
|
|
24
|
+
|
|
25
|
+
v0.3.13 - 23 Sep 2017
|
|
26
|
+
---
|
|
27
|
+
Updated dependencies.
|
|
28
|
+
|
|
29
|
+
v0.3.12 - 23 Sep 2017
|
|
30
|
+
---
|
|
31
|
+
Spec fixes.
|
|
32
|
+
Updated dependencies.
|
|
33
|
+
|
|
34
|
+
v0.3.11 - 1 Nov 2016
|
|
35
|
+
---
|
|
36
|
+
Removed `redis-semaphore` gem and use INCRBY to track pending concurrent tasks instead.
|
|
37
|
+
Added instrumentation using statsd.
|
|
38
|
+
Bug fixes to key expiry logic.
|
|
39
|
+
Refactored process and task state transistions.
|
|
40
|
+
|
|
41
|
+
v0.3.10 - 1 Nov 2016
|
|
42
|
+
---
|
|
43
|
+
Added support for serializing to XML.
|
|
44
|
+
Improvements to process and task states.
|
|
45
|
+
|
|
46
|
+
v0.3.9 - 12 Sep 2016
|
|
47
|
+
---
|
|
48
|
+
Added benchmark for redis-mutex.
|
|
49
|
+
|
|
50
|
+
v0.3.7 - 18 Aug 2016
|
|
51
|
+
---
|
|
52
|
+
Bug fix to `option?` method.
|
|
53
|
+
|
|
1
54
|
v0.3.6 - 11 Nov 2015
|
|
2
55
|
---
|
|
3
56
|
Added visitor for performing clean up of completed processes/tasks.
|
data/Gemfile
CHANGED
|
@@ -15,10 +15,10 @@ gem 'resque_spec' , '>= 0.16.0'
|
|
|
15
15
|
# other
|
|
16
16
|
gem 'bundler' , '>= 1.6.0'
|
|
17
17
|
gem 'rake' , '>= 10.3.0'
|
|
18
|
-
gem 'activesupport' , '~>
|
|
18
|
+
gem 'activesupport' , '~> 5.2.0'
|
|
19
19
|
gem 'rspec'
|
|
20
|
-
gem 'coveralls' , '>= 0.
|
|
20
|
+
gem 'coveralls' , '>= 0.8.22'
|
|
21
21
|
gem 'pry' , '>= 0.9.0'
|
|
22
22
|
gem 'pry-byebug' , '>= 1.3.0'
|
|
23
23
|
|
|
24
|
-
gem 'fakeredis' , '~> 0.
|
|
24
|
+
gem 'fakeredis' , '~> 0.7.0'
|
data/Gemfile.lock
CHANGED
|
@@ -1,115 +1,120 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
taskinator (0.
|
|
4
|
+
taskinator (0.4.1)
|
|
5
5
|
builder (>= 3.2.2)
|
|
6
6
|
connection_pool (>= 2.2.0)
|
|
7
7
|
globalid (~> 0.3)
|
|
8
8
|
json (>= 1.8.2)
|
|
9
9
|
redis (>= 3.2.1)
|
|
10
10
|
redis-namespace (>= 1.5.2)
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
statsd-ruby (~> 1.4.0)
|
|
12
|
+
thwait (~> 0.2)
|
|
13
13
|
|
|
14
14
|
GEM
|
|
15
15
|
remote: https://rubygems.org/
|
|
16
16
|
specs:
|
|
17
|
-
activesupport (
|
|
18
|
-
|
|
17
|
+
activesupport (5.2.4.5)
|
|
18
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
19
|
+
i18n (>= 0.7, < 2)
|
|
19
20
|
minitest (~> 5.1)
|
|
20
|
-
thread_safe (~> 0.3, >= 0.3.4)
|
|
21
21
|
tzinfo (~> 1.1)
|
|
22
|
-
builder (3.2.
|
|
23
|
-
byebug (
|
|
24
|
-
coderay (1.1.
|
|
25
|
-
concurrent-ruby (1.
|
|
26
|
-
connection_pool (2.2.
|
|
27
|
-
coveralls (0.8.
|
|
22
|
+
builder (3.2.4)
|
|
23
|
+
byebug (11.1.3)
|
|
24
|
+
coderay (1.1.3)
|
|
25
|
+
concurrent-ruby (1.1.8)
|
|
26
|
+
connection_pool (2.2.3)
|
|
27
|
+
coveralls (0.8.23)
|
|
28
28
|
json (>= 1.8, < 3)
|
|
29
|
-
simplecov (~> 0.
|
|
29
|
+
simplecov (~> 0.16.1)
|
|
30
30
|
term-ansicolor (~> 1.3)
|
|
31
|
-
thor (
|
|
31
|
+
thor (>= 0.19.4, < 2.0)
|
|
32
32
|
tins (~> 1.6)
|
|
33
|
-
delayed_job (4.1.
|
|
34
|
-
activesupport (>= 3.0, <
|
|
35
|
-
diff-lcs (1.
|
|
36
|
-
docile (1.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
delayed_job (4.1.9)
|
|
34
|
+
activesupport (>= 3.0, < 6.2)
|
|
35
|
+
diff-lcs (1.4.4)
|
|
36
|
+
docile (1.3.5)
|
|
37
|
+
e2mmap (0.1.0)
|
|
38
|
+
fakeredis (0.7.0)
|
|
39
|
+
redis (>= 3.2, < 5.0)
|
|
40
|
+
globalid (0.4.2)
|
|
40
41
|
activesupport (>= 4.2.0)
|
|
41
|
-
i18n (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
i18n (1.8.9)
|
|
43
|
+
concurrent-ruby (~> 1.0)
|
|
44
|
+
json (2.5.1)
|
|
45
|
+
method_source (1.0.0)
|
|
46
|
+
minitest (5.14.4)
|
|
45
47
|
mono_logger (1.1.0)
|
|
46
|
-
multi_json (1.
|
|
47
|
-
mustermann (1.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
rack
|
|
48
|
+
multi_json (1.15.0)
|
|
49
|
+
mustermann (1.1.1)
|
|
50
|
+
ruby2_keywords (~> 0.0.1)
|
|
51
|
+
pry (0.13.1)
|
|
52
|
+
coderay (~> 1.1)
|
|
53
|
+
method_source (~> 1.0)
|
|
54
|
+
pry-byebug (3.9.0)
|
|
55
|
+
byebug (~> 11.0)
|
|
56
|
+
pry (~> 0.13.0)
|
|
57
|
+
rack (2.2.3)
|
|
58
|
+
rack-protection (2.1.0)
|
|
56
59
|
rack
|
|
57
|
-
rake (
|
|
58
|
-
redis (
|
|
59
|
-
redis-namespace (1.
|
|
60
|
-
redis (
|
|
61
|
-
|
|
62
|
-
redis
|
|
63
|
-
resque (1.27.4)
|
|
60
|
+
rake (13.0.3)
|
|
61
|
+
redis (4.2.5)
|
|
62
|
+
redis-namespace (1.8.1)
|
|
63
|
+
redis (>= 3.0.4)
|
|
64
|
+
resque (2.0.0)
|
|
64
65
|
mono_logger (~> 1.0)
|
|
65
66
|
multi_json (~> 1.0)
|
|
66
|
-
redis-namespace (~> 1.
|
|
67
|
+
redis-namespace (~> 1.6)
|
|
67
68
|
sinatra (>= 0.9.2)
|
|
68
69
|
vegas (~> 0.1.2)
|
|
69
|
-
resque_spec (0.
|
|
70
|
-
resque (>= 1.
|
|
70
|
+
resque_spec (0.18.1)
|
|
71
|
+
resque (>= 1.26.0)
|
|
71
72
|
rspec-core (>= 3.0.0)
|
|
72
73
|
rspec-expectations (>= 3.0.0)
|
|
73
74
|
rspec-mocks (>= 3.0.0)
|
|
74
|
-
rspec (3.
|
|
75
|
-
rspec-core (~> 3.
|
|
76
|
-
rspec-expectations (~> 3.
|
|
77
|
-
rspec-mocks (~> 3.
|
|
78
|
-
rspec-core (3.
|
|
79
|
-
rspec-support (~> 3.
|
|
80
|
-
rspec-expectations (3.
|
|
75
|
+
rspec (3.10.0)
|
|
76
|
+
rspec-core (~> 3.10.0)
|
|
77
|
+
rspec-expectations (~> 3.10.0)
|
|
78
|
+
rspec-mocks (~> 3.10.0)
|
|
79
|
+
rspec-core (3.10.1)
|
|
80
|
+
rspec-support (~> 3.10.0)
|
|
81
|
+
rspec-expectations (3.10.1)
|
|
81
82
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
82
|
-
rspec-support (~> 3.
|
|
83
|
-
rspec-mocks (3.
|
|
83
|
+
rspec-support (~> 3.10.0)
|
|
84
|
+
rspec-mocks (3.10.2)
|
|
84
85
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
85
|
-
rspec-support (~> 3.
|
|
86
|
-
rspec-sidekiq (3.0
|
|
86
|
+
rspec-support (~> 3.10.0)
|
|
87
|
+
rspec-sidekiq (3.1.0)
|
|
87
88
|
rspec-core (~> 3.0, >= 3.0.0)
|
|
88
89
|
sidekiq (>= 2.4.0)
|
|
89
|
-
rspec-support (3.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
connection_pool (
|
|
93
|
-
rack
|
|
94
|
-
redis (
|
|
95
|
-
simplecov (0.
|
|
96
|
-
docile (~> 1.1
|
|
90
|
+
rspec-support (3.10.2)
|
|
91
|
+
ruby2_keywords (0.0.4)
|
|
92
|
+
sidekiq (6.1.3)
|
|
93
|
+
connection_pool (>= 2.2.2)
|
|
94
|
+
rack (~> 2.0)
|
|
95
|
+
redis (>= 4.2.0)
|
|
96
|
+
simplecov (0.16.1)
|
|
97
|
+
docile (~> 1.1)
|
|
97
98
|
json (>= 1.8, < 3)
|
|
98
99
|
simplecov-html (~> 0.10.0)
|
|
99
100
|
simplecov-html (0.10.2)
|
|
100
|
-
sinatra (2.
|
|
101
|
+
sinatra (2.1.0)
|
|
101
102
|
mustermann (~> 1.0)
|
|
102
|
-
rack (~> 2.
|
|
103
|
-
rack-protection (= 2.
|
|
103
|
+
rack (~> 2.2)
|
|
104
|
+
rack-protection (= 2.1.0)
|
|
104
105
|
tilt (~> 2.0)
|
|
105
|
-
statsd-ruby (1.
|
|
106
|
-
|
|
106
|
+
statsd-ruby (1.4.0)
|
|
107
|
+
sync (0.5.0)
|
|
108
|
+
term-ansicolor (1.7.1)
|
|
107
109
|
tins (~> 1.0)
|
|
108
|
-
thor (
|
|
110
|
+
thor (1.1.0)
|
|
109
111
|
thread_safe (0.3.6)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
thwait (0.2.0)
|
|
113
|
+
e2mmap
|
|
114
|
+
tilt (2.0.10)
|
|
115
|
+
tins (1.28.0)
|
|
116
|
+
sync
|
|
117
|
+
tzinfo (1.2.9)
|
|
113
118
|
thread_safe (~> 0.1)
|
|
114
119
|
vegas (0.1.11)
|
|
115
120
|
rack (>= 1.0.0)
|
|
@@ -118,11 +123,11 @@ PLATFORMS
|
|
|
118
123
|
ruby
|
|
119
124
|
|
|
120
125
|
DEPENDENCIES
|
|
121
|
-
activesupport (~>
|
|
126
|
+
activesupport (~> 5.2.0)
|
|
122
127
|
bundler (>= 1.6.0)
|
|
123
|
-
coveralls (>= 0.
|
|
128
|
+
coveralls (>= 0.8.22)
|
|
124
129
|
delayed_job (~> 4.1.0)
|
|
125
|
-
fakeredis (~> 0.
|
|
130
|
+
fakeredis (~> 0.7.0)
|
|
126
131
|
pry (>= 0.9.0)
|
|
127
132
|
pry-byebug (>= 1.3.0)
|
|
128
133
|
rake (>= 10.3.0)
|
|
@@ -134,4 +139,4 @@ DEPENDENCIES
|
|
|
134
139
|
taskinator!
|
|
135
140
|
|
|
136
141
|
BUNDLED WITH
|
|
137
|
-
|
|
142
|
+
2.2.14
|
data/README.md
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
[](http://travis-ci.org/virtualstaticvoid/taskinator)
|
|
5
5
|
[](https://codeclimate.com/github/virtualstaticvoid/taskinator)
|
|
6
6
|
[](https://coveralls.io/r/virtualstaticvoid/taskinator)
|
|
7
|
-
[](https://gemnasium.com/virtualstaticvoid/taskinator)
|
|
8
7
|
|
|
9
8
|
A simple orchestration library for running complex processes or workflows in Ruby. Processes are defined using a simple DSL, where the sequences and
|
|
10
9
|
tasks are defined. Processes can then be queued for execution. Sequences can be synchronous or asynchronous, and the overall process can be monitored
|
data/lib/taskinator.rb
CHANGED
|
@@ -24,7 +24,10 @@ module Taskinator
|
|
|
24
24
|
raise ArgumentError, 'block' unless block_given?
|
|
25
25
|
|
|
26
26
|
sub_process = Process.define_sequential_process_for(@definition, options)
|
|
27
|
-
|
|
27
|
+
task = define_sub_process_task(@process, sub_process, options)
|
|
28
|
+
Builder.new(sub_process, @definition, *@args).instance_eval(&block)
|
|
29
|
+
@process.tasks << task if sub_process.tasks.any?
|
|
30
|
+
nil
|
|
28
31
|
end
|
|
29
32
|
|
|
30
33
|
# defines a sub process of tasks which are executed concurrently
|
|
@@ -32,7 +35,10 @@ module Taskinator
|
|
|
32
35
|
raise ArgumentError, 'block' unless block_given?
|
|
33
36
|
|
|
34
37
|
sub_process = Process.define_concurrent_process_for(@definition, complete_on, options)
|
|
35
|
-
|
|
38
|
+
task = define_sub_process_task(@process, sub_process, options)
|
|
39
|
+
Builder.new(sub_process, @definition, *@args).instance_eval(&block)
|
|
40
|
+
@process.tasks << task if sub_process.tasks.any?
|
|
41
|
+
nil
|
|
36
42
|
end
|
|
37
43
|
|
|
38
44
|
# dynamically defines tasks, using the given @iterator method
|
|
@@ -51,6 +57,7 @@ module Taskinator
|
|
|
51
57
|
@executor.send(method, *method_args) do |*args|
|
|
52
58
|
Builder.new(@process, @definition, *args).instance_eval(&block)
|
|
53
59
|
end
|
|
60
|
+
nil
|
|
54
61
|
end
|
|
55
62
|
|
|
56
63
|
alias_method :transform, :for_each
|
|
@@ -61,6 +68,7 @@ module Taskinator
|
|
|
61
68
|
raise NoMethodError, method unless @executor.respond_to?(method)
|
|
62
69
|
|
|
63
70
|
define_step_task(@process, method, @args, options)
|
|
71
|
+
nil
|
|
64
72
|
end
|
|
65
73
|
|
|
66
74
|
# defines a task which executes the given @job
|
|
@@ -70,6 +78,7 @@ module Taskinator
|
|
|
70
78
|
raise ArgumentError, 'job' unless job.methods.include?(:perform) || job.instance_methods.include?(:perform)
|
|
71
79
|
|
|
72
80
|
define_job_task(@process, job, @args, options)
|
|
81
|
+
nil
|
|
73
82
|
end
|
|
74
83
|
|
|
75
84
|
# defines a sub process task, for the given @definition
|
|
@@ -82,7 +91,10 @@ module Taskinator
|
|
|
82
91
|
# TODO: decide whether the sub process to dynamically receive arguments
|
|
83
92
|
|
|
84
93
|
sub_process = definition.create_sub_process(*@args, combine_options(options))
|
|
85
|
-
|
|
94
|
+
task = define_sub_process_task(@process, sub_process, options)
|
|
95
|
+
Builder.new(sub_process, definition, *@args)
|
|
96
|
+
@process.tasks << task if sub_process.tasks.any?
|
|
97
|
+
nil
|
|
86
98
|
end
|
|
87
99
|
|
|
88
100
|
private
|
|
@@ -100,10 +112,7 @@ module Taskinator
|
|
|
100
112
|
end
|
|
101
113
|
|
|
102
114
|
def define_sub_process_task(process, sub_process, options={})
|
|
103
|
-
|
|
104
|
-
Task.define_sub_process_task(process, sub_process, combine_options(options))
|
|
105
|
-
}
|
|
106
|
-
sub_process
|
|
115
|
+
Task.define_sub_process_task(process, sub_process, combine_options(options))
|
|
107
116
|
end
|
|
108
117
|
|
|
109
118
|
def define_task(process)
|
data/lib/taskinator/process.rb
CHANGED
|
@@ -199,6 +199,12 @@ module Taskinator
|
|
|
199
199
|
end
|
|
200
200
|
|
|
201
201
|
def task_completed(task)
|
|
202
|
+
# deincrement the count of pending sequential tasks
|
|
203
|
+
pending = deincr_pending_tasks
|
|
204
|
+
|
|
205
|
+
Taskinator.statsd_client.count("taskinator.#{definition.name.underscore.parameterize}.pending", pending)
|
|
206
|
+
Taskinator.logger.info("Completed task for process '#{uuid}'. Pending is #{pending}.")
|
|
207
|
+
|
|
202
208
|
next_task = task.next
|
|
203
209
|
if next_task
|
|
204
210
|
next_task.enqueue!
|
|
@@ -258,9 +264,6 @@ module Taskinator
|
|
|
258
264
|
end
|
|
259
265
|
|
|
260
266
|
def task_completed(task)
|
|
261
|
-
# skip if failed
|
|
262
|
-
return if failed?
|
|
263
|
-
|
|
264
267
|
# deincrement the count of pending concurrent tasks
|
|
265
268
|
pending = deincr_pending_tasks
|
|
266
269
|
|
data/lib/taskinator/task.rb
CHANGED
|
@@ -230,12 +230,12 @@ module Taskinator
|
|
|
230
230
|
# NNB: if other job types are required, may need to implement how they get invoked here!
|
|
231
231
|
# FIXME: possible implement using ActiveJob instead, so it doesn't matter how the worker is implemented
|
|
232
232
|
|
|
233
|
-
if job.
|
|
233
|
+
if job.respond_to?(:perform)
|
|
234
234
|
# resque
|
|
235
|
-
job.perform(args)
|
|
235
|
+
job.perform(*args)
|
|
236
236
|
else
|
|
237
237
|
# delayedjob and sidekiq
|
|
238
|
-
job.new.perform(args)
|
|
238
|
+
job.new.perform(*args)
|
|
239
239
|
end
|
|
240
240
|
|
|
241
241
|
# ASSUMPTION: when the job returns, the task is considered to be complete
|
data/lib/taskinator/version.rb
CHANGED
|
@@ -75,6 +75,22 @@ describe Taskinator::Definition::Builder do
|
|
|
75
75
|
expect(Taskinator::Process).to receive(:define_sequential_process_for).with(definition, options).and_call_original
|
|
76
76
|
subject.sequential(options, &define_block)
|
|
77
77
|
end
|
|
78
|
+
|
|
79
|
+
it "adds sub-process task" do
|
|
80
|
+
block = Proc.new {|p|
|
|
81
|
+
p.task :task_method
|
|
82
|
+
}
|
|
83
|
+
expect(process.tasks).to be_empty
|
|
84
|
+
subject.sequential(options, &block)
|
|
85
|
+
expect(process.tasks).to_not be_empty
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "ignores sub-processes without tasks" do
|
|
89
|
+
allow(block).to receive(:call)
|
|
90
|
+
expect(process.tasks).to be_empty
|
|
91
|
+
subject.sequential(options, &define_block)
|
|
92
|
+
expect(process.tasks).to be_empty
|
|
93
|
+
end
|
|
78
94
|
end
|
|
79
95
|
|
|
80
96
|
describe "#concurrent" do
|
|
@@ -100,6 +116,22 @@ describe Taskinator::Definition::Builder do
|
|
|
100
116
|
expect(Taskinator::Process).to receive(:define_concurrent_process_for).with(definition, Taskinator::CompleteOn::First, options).and_call_original
|
|
101
117
|
subject.concurrent(Taskinator::CompleteOn::First, options, &define_block)
|
|
102
118
|
end
|
|
119
|
+
|
|
120
|
+
it "adds sub-process task" do
|
|
121
|
+
block = Proc.new {|p|
|
|
122
|
+
p.task :task_method
|
|
123
|
+
}
|
|
124
|
+
expect(process.tasks).to be_empty
|
|
125
|
+
subject.sequential(options, &block)
|
|
126
|
+
expect(process.tasks).to_not be_empty
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "ignores sub-processes without tasks" do
|
|
130
|
+
allow(block).to receive(:call)
|
|
131
|
+
expect(process.tasks).to be_empty
|
|
132
|
+
subject.sequential(options, &define_block)
|
|
133
|
+
expect(process.tasks).to be_empty
|
|
134
|
+
end
|
|
103
135
|
end
|
|
104
136
|
|
|
105
137
|
describe "#for_each" do
|
|
@@ -235,6 +267,22 @@ describe Taskinator::Definition::Builder do
|
|
|
235
267
|
expect(sub_definition).to receive(:create_sub_process).with(*args, builder_options.merge(options)).and_call_original
|
|
236
268
|
subject.sub_process(sub_definition, options)
|
|
237
269
|
end
|
|
270
|
+
|
|
271
|
+
it "adds sub-process task" do
|
|
272
|
+
block = Proc.new {|p|
|
|
273
|
+
p.task :task_method
|
|
274
|
+
}
|
|
275
|
+
expect(process.tasks).to be_empty
|
|
276
|
+
subject.sequential(options, &block)
|
|
277
|
+
expect(process.tasks).to_not be_empty
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it "ignores sub-processes without tasks" do
|
|
281
|
+
allow(block).to receive(:call)
|
|
282
|
+
expect(process.tasks).to be_empty
|
|
283
|
+
subject.sequential(options, &define_block)
|
|
284
|
+
expect(process.tasks).to be_empty
|
|
285
|
+
end
|
|
238
286
|
end
|
|
239
287
|
|
|
240
288
|
end
|
|
@@ -288,6 +288,23 @@ describe Taskinator::Process do
|
|
|
288
288
|
subject.task_completed(task1)
|
|
289
289
|
end
|
|
290
290
|
|
|
291
|
+
it "deincrements the pending task count" do
|
|
292
|
+
tasks.each {|t| subject.tasks << t }
|
|
293
|
+
task1 = tasks[0]
|
|
294
|
+
task2 = tasks[1]
|
|
295
|
+
|
|
296
|
+
allow(task2).to receive(:enqueue!)
|
|
297
|
+
|
|
298
|
+
pending_count = tasks.count
|
|
299
|
+
allow(subject).to receive(:deincr_pending_tasks) { pending_count -= 1 }
|
|
300
|
+
|
|
301
|
+
subject.task_completed(task1)
|
|
302
|
+
expect(pending_count).to eq(tasks.count - 1)
|
|
303
|
+
|
|
304
|
+
subject.task_completed(task2)
|
|
305
|
+
expect(pending_count).to eq(tasks.count - 2)
|
|
306
|
+
end
|
|
307
|
+
|
|
291
308
|
it "completes if no more tasks" do
|
|
292
309
|
tasks.each {|t| subject.tasks << t }
|
|
293
310
|
task2 = tasks[1]
|
|
@@ -296,6 +313,30 @@ describe Taskinator::Process do
|
|
|
296
313
|
|
|
297
314
|
subject.task_completed(task2)
|
|
298
315
|
end
|
|
316
|
+
|
|
317
|
+
it "completes if failed task gets retried" do
|
|
318
|
+
tasks.each {|t| subject.tasks << t }
|
|
319
|
+
task1 = tasks[0]
|
|
320
|
+
task2 = tasks[1]
|
|
321
|
+
|
|
322
|
+
allow(task2).to receive(:enqueue!)
|
|
323
|
+
|
|
324
|
+
expect(subject).to receive(:fail!).and_call_original
|
|
325
|
+
expect(subject).to receive(:complete!).and_call_original
|
|
326
|
+
|
|
327
|
+
subject.task_completed(task1)
|
|
328
|
+
expect(subject.completed?).to_not be
|
|
329
|
+
expect(subject.failed?).to_not be
|
|
330
|
+
|
|
331
|
+
subject.task_failed(task2, StandardError.new)
|
|
332
|
+
expect(subject.completed?).to_not be
|
|
333
|
+
expect(subject.failed?).to be
|
|
334
|
+
|
|
335
|
+
# "retry" the task
|
|
336
|
+
subject.task_completed(task2)
|
|
337
|
+
expect(subject.completed?).to be
|
|
338
|
+
expect(subject.failed?).to_not be
|
|
339
|
+
end
|
|
299
340
|
end
|
|
300
341
|
|
|
301
342
|
describe "#tasks_completed?" do
|
|
@@ -315,6 +356,28 @@ describe Taskinator::Process do
|
|
|
315
356
|
end
|
|
316
357
|
end
|
|
317
358
|
|
|
359
|
+
describe "#task_failed" do
|
|
360
|
+
it "fails when tasks fail" do
|
|
361
|
+
tasks.each {|t| subject.tasks << t }
|
|
362
|
+
|
|
363
|
+
error = StandardError.new
|
|
364
|
+
|
|
365
|
+
expect(subject).to receive(:fail!).with(error)
|
|
366
|
+
|
|
367
|
+
subject.task_failed(tasks.first, error)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it "doesn't deincement pending task count" do
|
|
371
|
+
tasks.each {|t| subject.tasks << t }
|
|
372
|
+
|
|
373
|
+
expect(subject).to_not receive(:deincr_pending_tasks)
|
|
374
|
+
|
|
375
|
+
error = StandardError.new
|
|
376
|
+
|
|
377
|
+
subject.task_failed(tasks.first, error)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
318
381
|
describe "#accept" do
|
|
319
382
|
it { expect(subject).to be_a(Taskinator::Persistence) }
|
|
320
383
|
|
|
@@ -422,7 +485,8 @@ describe Taskinator::Process do
|
|
|
422
485
|
process = Taskinator::Process.define_concurrent_process_for(definition, Taskinator::CompleteOn::First)
|
|
423
486
|
tasks.each {|t| process.tasks << t }
|
|
424
487
|
|
|
425
|
-
|
|
488
|
+
pending_count = tasks.count
|
|
489
|
+
allow(process).to receive(:deincr_pending_tasks) { pending_count -= 1 }
|
|
426
490
|
|
|
427
491
|
expect(process).to receive(:complete!).once.and_call_original
|
|
428
492
|
|
|
@@ -450,6 +514,82 @@ describe Taskinator::Process do
|
|
|
450
514
|
expect(process.completed?).to be(false) unless pending_count < 1
|
|
451
515
|
end
|
|
452
516
|
end
|
|
517
|
+
|
|
518
|
+
it "deincrements the pending task count" do
|
|
519
|
+
tasks.each {|t| subject.tasks << t }
|
|
520
|
+
task1 = tasks[0]
|
|
521
|
+
task2 = tasks[1]
|
|
522
|
+
|
|
523
|
+
pending_count = tasks.count
|
|
524
|
+
allow(subject).to receive(:deincr_pending_tasks) { pending_count -= 1 }
|
|
525
|
+
|
|
526
|
+
subject.task_completed(task1)
|
|
527
|
+
expect(pending_count).to eq(tasks.count - 1)
|
|
528
|
+
|
|
529
|
+
subject.task_completed(task2)
|
|
530
|
+
expect(pending_count).to eq(tasks.count - 2)
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
describe "completes if failed task gets retried" do
|
|
534
|
+
it "after first task succeeds" do
|
|
535
|
+
tasks.each {|t| subject.tasks << t }
|
|
536
|
+
task1 = tasks[0]
|
|
537
|
+
task2 = tasks[1]
|
|
538
|
+
|
|
539
|
+
pending_count = tasks.count
|
|
540
|
+
allow(subject).to receive(:deincr_pending_tasks) { pending_count -= 1 }
|
|
541
|
+
allow(task2).to receive(:enqueue!)
|
|
542
|
+
|
|
543
|
+
expect(subject).to receive(:fail!).and_call_original
|
|
544
|
+
expect(subject).to receive(:complete!).and_call_original
|
|
545
|
+
|
|
546
|
+
# first task succeeds
|
|
547
|
+
subject.task_completed(task1)
|
|
548
|
+
expect(pending_count).to eq(tasks.count - 1)
|
|
549
|
+
|
|
550
|
+
# second task fails
|
|
551
|
+
subject.task_failed(task2, StandardError.new)
|
|
552
|
+
|
|
553
|
+
expect(subject.failed?).to be
|
|
554
|
+
expect(pending_count).to eq(tasks.count - 1)
|
|
555
|
+
|
|
556
|
+
# "retry" the task
|
|
557
|
+
subject.task_completed(task2)
|
|
558
|
+
|
|
559
|
+
expect(pending_count).to eq(tasks.count - 2)
|
|
560
|
+
expect(subject.failed?).to_not be
|
|
561
|
+
expect(subject.completed?).to be
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
it "after first task fails" do
|
|
565
|
+
tasks.each {|t| subject.tasks << t }
|
|
566
|
+
task1 = tasks[0]
|
|
567
|
+
task2 = tasks[1]
|
|
568
|
+
|
|
569
|
+
pending_count = tasks.count
|
|
570
|
+
allow(subject).to receive(:deincr_pending_tasks) { pending_count -= 1 }
|
|
571
|
+
allow(task2).to receive(:enqueue!)
|
|
572
|
+
|
|
573
|
+
expect(subject).to receive(:fail!).and_call_original
|
|
574
|
+
expect(subject).to receive(:complete!).and_call_original
|
|
575
|
+
|
|
576
|
+
# first task fails
|
|
577
|
+
subject.task_failed(task2, StandardError.new)
|
|
578
|
+
expect(subject.failed?).to be
|
|
579
|
+
expect(pending_count).to eq(tasks.count)
|
|
580
|
+
|
|
581
|
+
# second task succeeds
|
|
582
|
+
subject.task_completed(task1)
|
|
583
|
+
expect(pending_count).to eq(tasks.count - 1)
|
|
584
|
+
|
|
585
|
+
# "retry" the task
|
|
586
|
+
subject.task_completed(task2)
|
|
587
|
+
|
|
588
|
+
expect(pending_count).to eq(tasks.count - 2)
|
|
589
|
+
expect(subject.failed?).to_not be
|
|
590
|
+
expect(subject.completed?).to be
|
|
591
|
+
end
|
|
592
|
+
end
|
|
453
593
|
end
|
|
454
594
|
|
|
455
595
|
describe "#task_failed" do
|
|
@@ -462,6 +602,16 @@ describe Taskinator::Process do
|
|
|
462
602
|
|
|
463
603
|
subject.task_failed(tasks.first, error)
|
|
464
604
|
end
|
|
605
|
+
|
|
606
|
+
it "doesn't deincement pending task count" do
|
|
607
|
+
tasks.each {|t| subject.tasks << t }
|
|
608
|
+
|
|
609
|
+
expect(subject).to_not receive(:deincr_pending_tasks)
|
|
610
|
+
|
|
611
|
+
error = StandardError.new
|
|
612
|
+
|
|
613
|
+
subject.task_failed(tasks.first, error)
|
|
614
|
+
end
|
|
465
615
|
end
|
|
466
616
|
|
|
467
617
|
describe "#tasks_completed?" do
|
|
@@ -227,7 +227,7 @@ describe Taskinator::Task do
|
|
|
227
227
|
|
|
228
228
|
method = subject.method
|
|
229
229
|
|
|
230
|
-
executor.class_eval do
|
|
230
|
+
executor.singleton_class.class_eval do
|
|
231
231
|
define_method method do |*args|
|
|
232
232
|
# this method executes in the scope of the executor
|
|
233
233
|
# store the context in an instance variable
|
|
@@ -334,13 +334,23 @@ describe Taskinator::Task do
|
|
|
334
334
|
end
|
|
335
335
|
end
|
|
336
336
|
|
|
337
|
-
|
|
337
|
+
class TestJobClassNoArgs
|
|
338
|
+
def perform
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
module TestJobModuleNoArgs
|
|
343
|
+
def self.perform
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
subject { Taskinator::Task.define_job_task(process, TestJob, [1, {:a => 1, :b => 2}]) }
|
|
338
348
|
|
|
339
349
|
it_should_behave_like "a task", Taskinator::Task::Job
|
|
340
350
|
|
|
341
351
|
describe ".define_job_task" do
|
|
342
352
|
it "sets the queue to use" do
|
|
343
|
-
task = Taskinator::Task.define_job_task(process, TestJob, {:a => 1, :b => 2}, :queue => :foo)
|
|
353
|
+
task = Taskinator::Task.define_job_task(process, TestJob, [1, {:a => 1, :b => 2}], :queue => :foo)
|
|
344
354
|
expect(task.queue).to eq(:foo)
|
|
345
355
|
end
|
|
346
356
|
end
|
|
@@ -367,23 +377,37 @@ describe Taskinator::Task do
|
|
|
367
377
|
|
|
368
378
|
describe "#start" do
|
|
369
379
|
it {
|
|
370
|
-
task = Taskinator::Task.define_job_task(process, TestJobClass, {:a => 1, :b => 2})
|
|
380
|
+
task = Taskinator::Task.define_job_task(process, TestJobClass, [1, {:a => 1, :b => 2}])
|
|
381
|
+
expect(process).to receive(:task_completed).with(task)
|
|
382
|
+
expect_any_instance_of(TestJobClass).to receive(:perform).with(1, {:a => 1, :b => 2})
|
|
383
|
+
task.start!
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
it {
|
|
387
|
+
task = Taskinator::Task.define_job_task(process, TestJobModule, [2, {:a => 1, :b => 2}])
|
|
388
|
+
expect(process).to receive(:task_completed).with(task)
|
|
389
|
+
expect(TestJobModule).to receive(:perform).with(2, {:a => 1, :b => 2})
|
|
390
|
+
task.start!
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
it {
|
|
394
|
+
task = Taskinator::Task.define_job_task(process, TestJobClassNoArgs, nil)
|
|
371
395
|
expect(process).to receive(:task_completed).with(task)
|
|
372
|
-
expect_any_instance_of(
|
|
396
|
+
expect_any_instance_of(TestJobClassNoArgs).to receive(:perform).and_call_original
|
|
373
397
|
task.start!
|
|
374
398
|
}
|
|
375
399
|
|
|
376
400
|
it {
|
|
377
|
-
task = Taskinator::Task.define_job_task(process,
|
|
401
|
+
task = Taskinator::Task.define_job_task(process, TestJobModuleNoArgs, nil)
|
|
378
402
|
expect(process).to receive(:task_completed).with(task)
|
|
379
|
-
expect(
|
|
403
|
+
expect(TestJobModuleNoArgs).to receive(:perform).and_call_original
|
|
380
404
|
task.start!
|
|
381
405
|
}
|
|
382
406
|
|
|
383
407
|
it "is instrumented" do
|
|
384
408
|
allow(process).to receive(:task_completed).with(subject)
|
|
385
409
|
|
|
386
|
-
allow(TestJob).to receive(:perform).with({:a => 1, :b => 2})
|
|
410
|
+
allow(TestJob).to receive(:perform).with(1, {:a => 1, :b => 2})
|
|
387
411
|
|
|
388
412
|
instrumentation_block = SpecSupport::Block.new
|
|
389
413
|
|
data/taskinator.gemspec
CHANGED
|
@@ -23,10 +23,11 @@ Gem::Specification.new do |spec|
|
|
|
23
23
|
# core
|
|
24
24
|
spec.add_dependency 'redis' , '>= 3.2.1'
|
|
25
25
|
spec.add_dependency 'redis-namespace' , '>= 1.5.2'
|
|
26
|
-
spec.add_dependency 'redis-semaphore' , '>= 0.2.4'
|
|
27
26
|
spec.add_dependency 'connection_pool' , '>= 2.2.0'
|
|
28
27
|
spec.add_dependency 'json' , '>= 1.8.2'
|
|
29
28
|
spec.add_dependency 'builder' , '>= 3.2.2'
|
|
30
29
|
spec.add_dependency 'globalid' , '~> 0.3'
|
|
31
|
-
spec.add_dependency 'statsd-ruby' , '~> 1.
|
|
30
|
+
spec.add_dependency 'statsd-ruby' , '~> 1.4.0'
|
|
31
|
+
spec.add_dependency 'thwait' , '~> 0.2'
|
|
32
|
+
|
|
32
33
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: taskinator
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Stefano
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-03-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: redis
|
|
@@ -38,20 +38,6 @@ dependencies:
|
|
|
38
38
|
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: 1.5.2
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: redis-semaphore
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - ">="
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.2.4
|
|
48
|
-
type: :runtime
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - ">="
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.2.4
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
42
|
name: connection_pool
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -114,14 +100,28 @@ dependencies:
|
|
|
114
100
|
requirements:
|
|
115
101
|
- - "~>"
|
|
116
102
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: 1.
|
|
103
|
+
version: 1.4.0
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 1.4.0
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: thwait
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0.2'
|
|
118
118
|
type: :runtime
|
|
119
119
|
prerelease: false
|
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
121
|
requirements:
|
|
122
122
|
- - "~>"
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
|
-
version:
|
|
124
|
+
version: '0.2'
|
|
125
125
|
description: Simple process orchestration
|
|
126
126
|
email:
|
|
127
127
|
- virtualstaticvoid@gmail.com
|
|
@@ -232,8 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
232
232
|
- !ruby/object:Gem::Version
|
|
233
233
|
version: '0'
|
|
234
234
|
requirements: []
|
|
235
|
-
|
|
236
|
-
rubygems_version: 2.6.13
|
|
235
|
+
rubygems_version: 3.1.4
|
|
237
236
|
signing_key:
|
|
238
237
|
specification_version: 4
|
|
239
238
|
summary: A simple orchestration library for running complex processes or workflows
|