taskinator 0.0.18 → 0.2.0
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/CHANGELOG.md +25 -0
- data/Gemfile.lock +28 -28
- data/README.md +29 -0
- data/Rakefile +5 -0
- data/bin/console +5 -0
- data/lib/taskinator/create_process_worker.rb +5 -2
- data/lib/taskinator/definition/builder.rb +12 -7
- data/lib/taskinator/definition.rb +36 -28
- data/lib/taskinator/executor.rb +4 -4
- data/lib/taskinator/job_worker.rb +5 -10
- data/lib/taskinator/logger.rb +1 -0
- data/lib/taskinator/persistence.rb +74 -36
- data/lib/taskinator/process.rb +75 -49
- data/lib/taskinator/queues/delayed_job.rb +1 -11
- data/lib/taskinator/queues/resque.rb +0 -15
- data/lib/taskinator/queues/sidekiq.rb +1 -14
- data/lib/taskinator/queues.rb +0 -5
- data/lib/taskinator/redis_connection.rb +1 -0
- data/lib/taskinator/task.rb +57 -57
- data/lib/taskinator/task_worker.rb +1 -8
- data/lib/taskinator/version.rb +1 -1
- data/lib/taskinator.rb +7 -6
- data/spec/examples/queue_adapter_examples.rb +0 -10
- data/spec/support/test_definition.rb +4 -0
- data/spec/support/test_flow.rb +2 -0
- data/spec/support/test_flows.rb +54 -3
- data/spec/support/test_queue.rb +41 -6
- data/spec/taskinator/create_process_worker_spec.rb +12 -3
- data/spec/taskinator/definition/builder_spec.rb +39 -9
- data/spec/taskinator/definition_spec.rb +19 -27
- data/spec/taskinator/executor_spec.rb +19 -1
- data/spec/taskinator/job_worker_spec.rb +0 -11
- data/spec/taskinator/persistence_spec.rb +122 -7
- data/spec/taskinator/process_spec.rb +39 -23
- data/spec/taskinator/queues/delayed_job_spec.rb +1 -19
- data/spec/taskinator/queues/resque_spec.rb +1 -22
- data/spec/taskinator/queues/sidekiq_spec.rb +1 -20
- data/spec/taskinator/task_spec.rb +160 -52
- data/spec/taskinator/task_worker_spec.rb +0 -17
- data/spec/taskinator/test_flows_spec.rb +43 -0
- metadata +2 -5
- data/lib/taskinator/process_worker.rb +0 -21
- data/spec/taskinator/process_worker_spec.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1905dc0aad01e4bd348ad38a40100df9649e3a18
|
4
|
+
data.tar.gz: d1e4aa938c9d3a0d56fc4090f71024dec84e32fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cd0c7d2fa8d1f133ddce568ae969fe488401ba9f6311c39143456749b4eea1429edbc63ec080a5a8b60fb84bf312bdcd5758084269b16ae83b7b437877e15d1
|
7
|
+
data.tar.gz: dfcbeced7346f8c0bdcc70e5814e2b2e943ecd10182ac0285a88e8e0bdfc0eb1a227c900390328861bb4012e4feffbf8fe7d41033583d68eb1f25d198f1ef027
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
v0.2.0 - 31 Jul 2015
|
2
|
+
---
|
3
|
+
Bug fix for `create_process_remotely` so that it returns the process uuid instead of nil.
|
4
|
+
Removed reload functionality, since it isn't used anymore
|
5
|
+
Added missing instrumentation events for task, job and subprocess completed events.
|
6
|
+
Bug fix for when `sequential` or `concurrent` steps don't have any tasks to still continue processing.
|
7
|
+
Refactoring to remove dead code and "reload" functionality.
|
8
|
+
Improvements to console and rake to use console instrumenter.
|
9
|
+
Consolidation of instrumentation events. Added `type` to payload.
|
10
|
+
Improvements to error handling.
|
11
|
+
|
12
|
+
v0.1.1 - 23 Jul 2015 [Yanked]
|
13
|
+
---
|
14
|
+
Bug fix for option parameter handling.
|
15
|
+
|
16
|
+
v0.1.0 - 23 Jul 2015 [Yanked]
|
17
|
+
---
|
18
|
+
Fixed issue with persistence of options passed to `create_process` on the respective `Process` and `Task` instances.
|
19
|
+
Improvements to process creation logic.
|
20
|
+
Namespaced instrumentation event names.
|
21
|
+
Added process completed, cancelled and failed instrumentation events.
|
22
|
+
Include additional data in the instrumentation payload. E.g. Process options and percentages.
|
23
|
+
Refactored the way processes/tasks get queued, to prevent unnecessary queuing of contained processes/tasks.
|
24
|
+
Removed `ProcessWorker` since it isn't needed anymore.
|
25
|
+
|
1
26
|
v0.0.18 - 14 Jul 2015
|
2
27
|
---
|
3
28
|
Fixed issue with `Taskinator::Api::Processes#each` method, which was causing a Segmentation fault.
|
data/Gemfile.lock
CHANGED
@@ -8,7 +8,7 @@ GIT
|
|
8
8
|
PATH
|
9
9
|
remote: .
|
10
10
|
specs:
|
11
|
-
taskinator (0.0
|
11
|
+
taskinator (0.2.0)
|
12
12
|
connection_pool (>= 2.2.0)
|
13
13
|
json (>= 1.8.2)
|
14
14
|
redis (>= 3.2.1)
|
@@ -17,20 +17,20 @@ PATH
|
|
17
17
|
GEM
|
18
18
|
remote: https://rubygems.org/
|
19
19
|
specs:
|
20
|
-
activesupport (4.2.
|
20
|
+
activesupport (4.2.3)
|
21
21
|
i18n (~> 0.7)
|
22
22
|
json (~> 1.7, >= 1.7.7)
|
23
23
|
minitest (~> 5.1)
|
24
24
|
thread_safe (~> 0.3, >= 0.3.4)
|
25
25
|
tzinfo (~> 1.1)
|
26
|
-
byebug (
|
26
|
+
byebug (5.0.0)
|
27
27
|
columnize (= 0.9.0)
|
28
28
|
celluloid (0.16.0)
|
29
29
|
timers (~> 4.0.0)
|
30
30
|
coderay (1.1.0)
|
31
31
|
columnize (0.9.0)
|
32
32
|
connection_pool (2.2.0)
|
33
|
-
coveralls (0.8.
|
33
|
+
coveralls (0.8.2)
|
34
34
|
json (~> 1.8)
|
35
35
|
rest-client (>= 1.6.8, < 2)
|
36
36
|
simplecov (~> 0.10.0)
|
@@ -46,21 +46,21 @@ GEM
|
|
46
46
|
http-cookie (1.0.2)
|
47
47
|
domain_name (~> 0.5)
|
48
48
|
i18n (0.7.0)
|
49
|
-
json (1.8.
|
49
|
+
json (1.8.3)
|
50
50
|
method_source (0.8.2)
|
51
51
|
mime-types (2.6.1)
|
52
52
|
minitest (5.7.0)
|
53
53
|
mono_logger (1.1.0)
|
54
|
-
multi_json (1.11.
|
54
|
+
multi_json (1.11.2)
|
55
55
|
netrc (0.10.3)
|
56
56
|
pry (0.10.1)
|
57
57
|
coderay (~> 1.1.0)
|
58
58
|
method_source (~> 0.8.1)
|
59
59
|
slop (~> 3.4)
|
60
|
-
pry-byebug (3.
|
61
|
-
byebug (~>
|
60
|
+
pry-byebug (3.2.0)
|
61
|
+
byebug (~> 5.0)
|
62
62
|
pry (~> 0.10)
|
63
|
-
rack (1.6.
|
63
|
+
rack (1.6.4)
|
64
64
|
rack-protection (1.5.3)
|
65
65
|
rack
|
66
66
|
rake (10.4.2)
|
@@ -82,28 +82,28 @@ GEM
|
|
82
82
|
http-cookie (>= 1.0.2, < 2.0)
|
83
83
|
mime-types (>= 1.16, < 3.0)
|
84
84
|
netrc (~> 0.7)
|
85
|
-
rspec (3.
|
86
|
-
rspec-core (~> 3.
|
87
|
-
rspec-expectations (~> 3.
|
88
|
-
rspec-mocks (~> 3.
|
89
|
-
rspec-core (3.2
|
90
|
-
rspec-support (~> 3.
|
91
|
-
rspec-expectations (3.
|
85
|
+
rspec (3.3.0)
|
86
|
+
rspec-core (~> 3.3.0)
|
87
|
+
rspec-expectations (~> 3.3.0)
|
88
|
+
rspec-mocks (~> 3.3.0)
|
89
|
+
rspec-core (3.3.2)
|
90
|
+
rspec-support (~> 3.3.0)
|
91
|
+
rspec-expectations (3.3.1)
|
92
92
|
diff-lcs (>= 1.2.0, < 2.0)
|
93
|
-
rspec-support (~> 3.
|
94
|
-
rspec-mocks (3.2
|
93
|
+
rspec-support (~> 3.3.0)
|
94
|
+
rspec-mocks (3.3.2)
|
95
95
|
diff-lcs (>= 1.2.0, < 2.0)
|
96
|
-
rspec-support (~> 3.
|
96
|
+
rspec-support (~> 3.3.0)
|
97
97
|
rspec-sidekiq (2.0.0)
|
98
98
|
rspec (~> 3.0, >= 3.0.0)
|
99
99
|
sidekiq (>= 2.4.0)
|
100
|
-
rspec-support (3.
|
101
|
-
sidekiq (3.
|
102
|
-
celluloid (
|
103
|
-
connection_pool (>= 2.
|
104
|
-
json
|
105
|
-
redis (>= 3.
|
106
|
-
redis-namespace (>= 1.
|
100
|
+
rspec-support (3.3.0)
|
101
|
+
sidekiq (3.4.2)
|
102
|
+
celluloid (~> 0.16.0)
|
103
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
104
|
+
json (~> 1.0)
|
105
|
+
redis (~> 3.2, >= 3.2.1)
|
106
|
+
redis-namespace (~> 1.5, >= 1.5.2)
|
107
107
|
simplecov (0.10.0)
|
108
108
|
docile (~> 1.1.0)
|
109
109
|
json (~> 1.8)
|
@@ -114,14 +114,14 @@ GEM
|
|
114
114
|
rack-protection (~> 1.4)
|
115
115
|
tilt (>= 1.3, < 3)
|
116
116
|
slop (3.6.0)
|
117
|
-
term-ansicolor (1.3.
|
117
|
+
term-ansicolor (1.3.2)
|
118
118
|
tins (~> 1.0)
|
119
119
|
thor (0.19.1)
|
120
120
|
thread_safe (0.3.5)
|
121
121
|
tilt (2.0.1)
|
122
122
|
timers (4.0.1)
|
123
123
|
hitimes
|
124
|
-
tins (1.5.
|
124
|
+
tins (1.5.4)
|
125
125
|
tzinfo (1.2.2)
|
126
126
|
thread_safe (~> 0.1)
|
127
127
|
unf (0.1.4)
|
data/README.md
CHANGED
@@ -606,6 +606,35 @@ Taskinator.configure do |config|
|
|
606
606
|
end
|
607
607
|
```
|
608
608
|
|
609
|
+
The following instrumentation events are issued:
|
610
|
+
|
611
|
+
| Event | When |
|
612
|
+
|------------------------------------|---------------------------------------------|
|
613
|
+
| `taskinator.process.created` | After a process gets created |
|
614
|
+
| `taskinator.process.saved` | After a process has been persisted to Redis |
|
615
|
+
| `taskinator.process.enqueued` | After a process is enqueued for processing |
|
616
|
+
| `taskinator.process.completed` | After a process has completed processing |
|
617
|
+
| `taskinator.process.cancelled` | After a process has been cancelled |
|
618
|
+
| `taskinator.process.failed` | After a process has failed |
|
619
|
+
| `taskinator.task.enqueued` | After a task has been enqueued |
|
620
|
+
| `taskinator.task.executed` | After a task has executed |
|
621
|
+
| `taskinator.job.enqueued` | After a job has been enqueued |
|
622
|
+
| `taskinator.job.executed` | After a job has executed |
|
623
|
+
| `taskinator.subprocess.enqueued` | After a sub process has been enqueued |
|
624
|
+
| `taskinator.subprocess.executed` | After a sub process has executed |
|
625
|
+
|
626
|
+
For all events, the data included contains the following information:
|
627
|
+
|
628
|
+
| Key | Value |
|
629
|
+
|--------------------------|-------------------------------------------------------|
|
630
|
+
| `:process_uuid` | The UUID of the root process |
|
631
|
+
| `:process_options` | Options hash of the root process |
|
632
|
+
| `:uuid` | The UUID of the respective task, job or sub process |
|
633
|
+
| `:tasks_count` | The total count of tasks for the given process |
|
634
|
+
| `:percentage_completed` | The percentage of completed tasks |
|
635
|
+
| `:percentage_failed` | The percentage of failed tasks |
|
636
|
+
| `:percentage_cancelled` | The percentage of cancelled tasks |
|
637
|
+
|
609
638
|
## Notes
|
610
639
|
|
611
640
|
The persistence logic is decoupled from the implementation, so it is possible to implement another backing store if required.
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -7,5 +7,10 @@ require "taskinator"
|
|
7
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
8
8
|
# with your gem easier. You can also use a different console, if you like.
|
9
9
|
|
10
|
+
Taskinator.configure do |config|
|
11
|
+
config.logger.level = 0 # DEBUG
|
12
|
+
config.instrumenter = Taskinator::ConsoleInstrumenter.new
|
13
|
+
end
|
14
|
+
|
10
15
|
require "pry"
|
11
16
|
Pry.start
|
@@ -19,13 +19,16 @@ module Taskinator
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def perform
|
22
|
-
@definition._create_process_(*@args, :uuid => @uuid).enqueue!
|
22
|
+
@definition._create_process_(false, *@args, :uuid => @uuid).enqueue!
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
26
26
|
|
27
|
-
#
|
27
|
+
# :nocov:
|
28
28
|
def constantize(camel_cased_word)
|
29
|
+
|
30
|
+
# borrowed from activesupport/lib/active_support/inflector/methods.rb
|
31
|
+
|
29
32
|
names = camel_cased_word.split('::')
|
30
33
|
|
31
34
|
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
@@ -5,18 +5,18 @@ module Taskinator
|
|
5
5
|
attr_reader :process
|
6
6
|
attr_reader :definition
|
7
7
|
attr_reader :args
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :builder_options
|
9
9
|
|
10
10
|
def initialize(process, definition, *args)
|
11
11
|
@process = process
|
12
12
|
@definition = definition
|
13
|
+
@builder_options = args.last.is_a?(Hash) ? args.pop : {}
|
13
14
|
@args = args
|
14
|
-
@options = args.last.is_a?(Hash) ? args.last : {}
|
15
15
|
@executor = Taskinator::Executor.new(@definition)
|
16
16
|
end
|
17
17
|
|
18
18
|
def option?(key, &block)
|
19
|
-
yield if
|
19
|
+
yield if builder_options.key?(key) && builder_options[key]
|
20
20
|
end
|
21
21
|
|
22
22
|
# defines a sub process of tasks which are executed sequentially
|
@@ -81,7 +81,7 @@ module Taskinator
|
|
81
81
|
|
82
82
|
# TODO: decide whether the sub process to dynamically receive arguments
|
83
83
|
|
84
|
-
sub_process = definition.create_sub_process(*@args)
|
84
|
+
sub_process = definition.create_sub_process(*@args, combine_options(options))
|
85
85
|
Builder.new(define_sub_process_task(@process, sub_process, options), definition, *@args)
|
86
86
|
end
|
87
87
|
|
@@ -89,19 +89,19 @@ module Taskinator
|
|
89
89
|
|
90
90
|
def define_step_task(process, method, args, options={})
|
91
91
|
define_task(process) {
|
92
|
-
Task.define_step_task(process, method, args, options)
|
92
|
+
Task.define_step_task(process, method, args, combine_options(options))
|
93
93
|
}
|
94
94
|
end
|
95
95
|
|
96
96
|
def define_job_task(process, job, args, options={})
|
97
97
|
define_task(process) {
|
98
|
-
Task.define_job_task(process, job, args, options)
|
98
|
+
Task.define_job_task(process, job, args, combine_options(options))
|
99
99
|
}
|
100
100
|
end
|
101
101
|
|
102
102
|
def define_sub_process_task(process, sub_process, options={})
|
103
103
|
define_task(process) {
|
104
|
-
Task.define_sub_process_task(process, sub_process, options)
|
104
|
+
Task.define_sub_process_task(process, sub_process, combine_options(options))
|
105
105
|
}
|
106
106
|
sub_process
|
107
107
|
end
|
@@ -110,6 +110,11 @@ module Taskinator
|
|
110
110
|
process.tasks << task = yield
|
111
111
|
task
|
112
112
|
end
|
113
|
+
|
114
|
+
def combine_options(options={})
|
115
|
+
builder_options.merge(options)
|
116
|
+
end
|
117
|
+
|
113
118
|
end
|
114
119
|
end
|
115
120
|
end
|
@@ -33,42 +33,49 @@ module Taskinator
|
|
33
33
|
Process.define_sequential_process_for(definition, options)
|
34
34
|
}
|
35
35
|
|
36
|
-
|
36
|
+
# called from respective "create_process" methods
|
37
|
+
# parameters can contain options as the last parameter
|
38
|
+
define_singleton_method :_create_process_ do |subprocess, *args|
|
39
|
+
begin
|
37
40
|
|
38
|
-
|
41
|
+
# TODO: better validation of arguments
|
39
42
|
|
40
|
-
|
43
|
+
# FIXME: arg_list should only contain an array of symbols
|
41
44
|
|
42
|
-
|
45
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for #{arg_list.length})" if args.length < arg_list.length
|
43
46
|
|
44
|
-
|
47
|
+
options = (args.last.is_a?(Hash) ? args.last : {})
|
48
|
+
process = factory.call(self, options)
|
45
49
|
|
46
|
-
|
50
|
+
# this may take long... up to users definition
|
51
|
+
Taskinator.instrumenter.instrument('taskinator.process.created', :uuid => process.uuid) do
|
52
|
+
Builder.new(process, self, *args).instance_eval(&block)
|
53
|
+
end
|
47
54
|
|
48
|
-
|
49
|
-
|
50
|
-
Builder.new(process, self, *args).instance_eval(&block)
|
51
|
-
end
|
55
|
+
# only save "root processes"
|
56
|
+
unless subprocess
|
52
57
|
|
53
|
-
|
54
|
-
|
58
|
+
# instrument separately
|
59
|
+
Taskinator.instrumenter.instrument('taskinator.process.saved', :uuid => process.uuid) do
|
55
60
|
|
56
|
-
|
57
|
-
|
61
|
+
# this will visit "sub processes" and persist them too
|
62
|
+
process.save
|
58
63
|
|
59
|
-
|
60
|
-
|
64
|
+
# add it to the list of "root processes"
|
65
|
+
Persistence.add_process_to_list(process)
|
61
66
|
|
62
|
-
|
63
|
-
Persistence.add_process_to_list(process)
|
67
|
+
end
|
64
68
|
|
65
69
|
end
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
# this is the "root" process
|
70
|
-
process
|
71
|
+
# this is the "root" process
|
72
|
+
process
|
71
73
|
|
74
|
+
rescue => e
|
75
|
+
Taskinator.logger.error(e)
|
76
|
+
Taskinator.logger.debug(e.backtrace)
|
77
|
+
raise e
|
78
|
+
end
|
72
79
|
end
|
73
80
|
end
|
74
81
|
|
@@ -80,25 +87,26 @@ module Taskinator
|
|
80
87
|
#
|
81
88
|
def create_process(*args)
|
82
89
|
assert_valid_process_module
|
83
|
-
_create_process_(*args
|
90
|
+
_create_process_(false, *args)
|
84
91
|
end
|
85
92
|
|
86
93
|
#
|
87
|
-
# returns
|
88
|
-
#
|
89
|
-
#
|
94
|
+
# returns the process uuid of the process to be created
|
95
|
+
# the process can be retrieved using this uuid by using
|
96
|
+
# Taskinator::Process.fetch(uuid)
|
90
97
|
#
|
91
98
|
def create_process_remotely(*args)
|
92
99
|
assert_valid_process_module
|
93
100
|
uuid = SecureRandom.uuid
|
101
|
+
|
94
102
|
Taskinator.queue.enqueue_create_process(self, uuid, args)
|
95
103
|
|
96
|
-
|
104
|
+
return uuid
|
97
105
|
end
|
98
106
|
|
99
107
|
def create_sub_process(*args)
|
100
108
|
assert_valid_process_module
|
101
|
-
_create_process_(*args
|
109
|
+
_create_process_(true, *args)
|
102
110
|
end
|
103
111
|
|
104
112
|
private
|
data/lib/taskinator/executor.rb
CHANGED
@@ -13,16 +13,16 @@ module Taskinator
|
|
13
13
|
eigen.send(:include, definition)
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
16
|
+
def process_uuid
|
17
|
+
task.process_uuid if task
|
18
18
|
end
|
19
19
|
|
20
20
|
def uuid
|
21
|
-
task.uuid
|
21
|
+
task.uuid if task
|
22
22
|
end
|
23
23
|
|
24
24
|
def options
|
25
|
-
task.options
|
25
|
+
task.options if task
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
@@ -1,22 +1,17 @@
|
|
1
1
|
module Taskinator
|
2
2
|
class JobWorker
|
3
|
+
attr_reader :uuid
|
4
|
+
|
3
5
|
def initialize(uuid)
|
4
6
|
@uuid = uuid
|
5
7
|
end
|
6
8
|
|
7
|
-
# NB: must be provided a block for the
|
9
|
+
# NB: must be provided a block for the implementation of the job execution
|
8
10
|
def perform(&block)
|
9
11
|
task = Taskinator::Task.fetch(@uuid)
|
10
12
|
return if task.paused? || task.cancelled?
|
11
|
-
|
12
|
-
|
13
|
-
task.perform(&block)
|
14
|
-
task.complete!
|
15
|
-
rescue => e
|
16
|
-
Taskinator.logger.error(e)
|
17
|
-
task.fail!(e)
|
18
|
-
raise e
|
19
|
-
end
|
13
|
+
task.start!
|
14
|
+
task.perform(&block)
|
20
15
|
end
|
21
16
|
end
|
22
17
|
end
|
data/lib/taskinator/logger.rb
CHANGED
@@ -40,10 +40,10 @@ module Taskinator
|
|
40
40
|
# querying for the status of an instance
|
41
41
|
def state_for(uuid)
|
42
42
|
key = key_for(uuid)
|
43
|
-
Taskinator.redis do |conn|
|
44
|
-
|
45
|
-
state.to_sym
|
43
|
+
state = Taskinator.redis do |conn|
|
44
|
+
conn.hget(key, :state) || 'initial'
|
46
45
|
end
|
46
|
+
state.to_sym
|
47
47
|
end
|
48
48
|
|
49
49
|
# fetches the instance for given identifier
|
@@ -67,7 +67,7 @@ module Taskinator
|
|
67
67
|
conn.multi do
|
68
68
|
visitor = RedisSerializationVisitor.new(conn, self).visit
|
69
69
|
conn.hmset(
|
70
|
-
|
70
|
+
Taskinator::Process.key_for(uuid),
|
71
71
|
:tasks_count, visitor.task_count,
|
72
72
|
:tasks_failed, 0,
|
73
73
|
:tasks_completed, 0,
|
@@ -78,19 +78,23 @@ module Taskinator
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
#
|
81
|
+
# the persistence key
|
82
82
|
def key
|
83
83
|
@key ||= self.class.key_for(self.uuid)
|
84
84
|
end
|
85
85
|
|
86
|
-
#
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
conn.hget(self.key, :root_key)
|
86
|
+
# the root process uuid associated with this process or task
|
87
|
+
def process_uuid
|
88
|
+
@process_uuid ||= Taskinator.redis do |conn|
|
89
|
+
conn.hget(self.key, :process_uuid)
|
91
90
|
end
|
92
91
|
end
|
93
92
|
|
93
|
+
# the root process persistence key associated with this process or task
|
94
|
+
def process_key
|
95
|
+
@process_key ||= Taskinator::Process.key_for(process_uuid)
|
96
|
+
end
|
97
|
+
|
94
98
|
# retrieves the workflow state
|
95
99
|
# this method is called from the workflow gem
|
96
100
|
def load_workflow_state
|
@@ -135,9 +139,10 @@ module Taskinator
|
|
135
139
|
|
136
140
|
def tasks_count
|
137
141
|
@tasks_count ||= begin
|
138
|
-
Taskinator.redis do |conn|
|
139
|
-
conn.hget
|
140
|
-
end
|
142
|
+
count = Taskinator.redis do |conn|
|
143
|
+
conn.hget self.process_key, :tasks_count
|
144
|
+
end
|
145
|
+
count.to_i
|
141
146
|
end
|
142
147
|
end
|
143
148
|
|
@@ -148,14 +153,15 @@ module Taskinator
|
|
148
153
|
).each do |status|
|
149
154
|
|
150
155
|
define_method "count_#{status}" do
|
151
|
-
Taskinator.redis do |conn|
|
152
|
-
conn.hget
|
153
|
-
end
|
156
|
+
count = Taskinator.redis do |conn|
|
157
|
+
conn.hget self.process_key, status
|
158
|
+
end
|
159
|
+
count.to_i
|
154
160
|
end
|
155
161
|
|
156
162
|
define_method "incr_#{status}" do
|
157
163
|
Taskinator.redis do |conn|
|
158
|
-
conn.hincrby
|
164
|
+
conn.hincrby self.process_key, status, 1
|
159
165
|
end
|
160
166
|
end
|
161
167
|
|
@@ -165,6 +171,46 @@ module Taskinator
|
|
165
171
|
|
166
172
|
end
|
167
173
|
|
174
|
+
# retrieves the process options of the root process
|
175
|
+
# this is so that meta data of the process can be maintained
|
176
|
+
# and accessible to instrumentation subscribers
|
177
|
+
def process_options
|
178
|
+
@process_options ||= begin
|
179
|
+
yaml = Taskinator.redis do |conn|
|
180
|
+
conn.hget(self.process_key, :options)
|
181
|
+
end
|
182
|
+
yaml ? Taskinator::Persistence.deserialize(yaml) : {}
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# prepairs the meta data for instrumentation events
|
187
|
+
def instrumentation_payload(additional={})
|
188
|
+
|
189
|
+
# need to cache here, since this method hits redis, so can't be part of multi statement following
|
190
|
+
process_key = self.process_key
|
191
|
+
|
192
|
+
tasks_count, completed_count, cancelled_count, failed_count = Taskinator.redis do |conn|
|
193
|
+
conn.hmget process_key, :tasks_count, :completed, :cancelled, :failed
|
194
|
+
end
|
195
|
+
|
196
|
+
tasks_count = tasks_count.to_f
|
197
|
+
completed_percent = tasks_count > 0 ? (completed_count.to_i / tasks_count) * 100.0 : 0.0
|
198
|
+
cancelled_percent = tasks_count > 0 ? (cancelled_count.to_i / tasks_count) * 100.0 : 0.0
|
199
|
+
failed_percent = tasks_count > 0 ? (failed_count.to_i / tasks_count) * 100.0 : 0.0
|
200
|
+
|
201
|
+
return {
|
202
|
+
:type => self.class.name,
|
203
|
+
:process_uuid => process_uuid,
|
204
|
+
:process_options => process_options,
|
205
|
+
:uuid => uuid,
|
206
|
+
:percentage_failed => failed_percent,
|
207
|
+
:percentage_cancelled => cancelled_percent,
|
208
|
+
:percentage_completed => completed_percent,
|
209
|
+
:tasks_count => tasks_count
|
210
|
+
}.merge(additional)
|
211
|
+
|
212
|
+
end
|
213
|
+
|
168
214
|
end
|
169
215
|
|
170
216
|
class RedisSerializationVisitor < Visitor::Base
|
@@ -181,7 +227,7 @@ module Taskinator
|
|
181
227
|
@conn = conn
|
182
228
|
@instance = instance
|
183
229
|
@key = instance.key
|
184
|
-
@
|
230
|
+
@root = base_visitor.instance
|
185
231
|
@base_visitor = base_visitor
|
186
232
|
@task_count = 0
|
187
233
|
end
|
@@ -195,8 +241,8 @@ module Taskinator
|
|
195
241
|
|
196
242
|
@instance.accept(self)
|
197
243
|
|
198
|
-
# add the root key, for easy access later!
|
199
|
-
@hmset += [:
|
244
|
+
# add the process uuid and root key, for easy access later!
|
245
|
+
@hmset += [:process_uuid, @root.uuid]
|
200
246
|
|
201
247
|
# NB: splat args
|
202
248
|
@conn.hmset(*@hmset)
|
@@ -359,13 +405,11 @@ module Taskinator
|
|
359
405
|
# arbitrary instance to perform it's work
|
360
406
|
#
|
361
407
|
def lazy_instance_for(base, uuid)
|
362
|
-
Taskinator.redis do |conn|
|
363
|
-
|
364
|
-
root_key = conn.hget(base.key_for(uuid), :root_key)
|
365
|
-
|
366
|
-
klass = Kernel.const_get(type)
|
367
|
-
LazyLoader.new(klass, uuid, root_key, @instance_cache)
|
408
|
+
type, process_uuid = Taskinator.redis do |conn|
|
409
|
+
conn.hmget(base.key_for(uuid), :type, :process_uuid)
|
368
410
|
end
|
411
|
+
klass = Kernel.const_get(type)
|
412
|
+
LazyLoader.new(klass, uuid, process_uuid, @instance_cache)
|
369
413
|
end
|
370
414
|
end
|
371
415
|
|
@@ -380,29 +424,23 @@ module Taskinator
|
|
380
424
|
# E.g. this is useful for tasks which refer to their parent processes
|
381
425
|
#
|
382
426
|
|
383
|
-
def initialize(type, uuid,
|
427
|
+
def initialize(type, uuid, process_uuid, instance_cache={})
|
384
428
|
@type = type
|
385
429
|
@uuid = uuid
|
386
|
-
@
|
430
|
+
@process_uuid = process_uuid
|
387
431
|
@instance_cache = instance_cache
|
388
432
|
end
|
389
433
|
|
390
434
|
# shadows the real methods, but will be the same!
|
435
|
+
attr_reader :process_uuid
|
391
436
|
attr_reader :uuid
|
392
|
-
attr_reader :root_key
|
393
|
-
|
394
|
-
# attempts to reload the actual process
|
395
|
-
def reload
|
396
|
-
@instance = nil
|
397
|
-
__getobj__
|
398
|
-
@instance ? true : false
|
399
|
-
end
|
400
437
|
|
401
438
|
def __getobj__
|
402
439
|
# only fetch the object as needed
|
403
440
|
# and memoize for subsequent calls
|
404
441
|
@instance ||= @type.fetch(@uuid, @instance_cache)
|
405
442
|
end
|
443
|
+
|
406
444
|
end
|
407
445
|
|
408
446
|
class << self
|