taskinator 0.2.0 → 0.3.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 +10 -0
- data/Gemfile +17 -2
- data/Gemfile.lock +57 -18
- data/README.md +20 -16
- data/lib/taskinator/definition.rb +2 -2
- data/lib/taskinator/instrumentation.rb +77 -0
- data/lib/taskinator/persistence.rb +72 -61
- data/lib/taskinator/process.rb +118 -99
- data/lib/taskinator/queues/delayed_job.rb +0 -14
- data/lib/taskinator/queues/resque.rb +0 -18
- data/lib/taskinator/queues/sidekiq.rb +0 -14
- data/lib/taskinator/queues.rb +0 -5
- data/lib/taskinator/task.rb +113 -70
- data/lib/taskinator/version.rb +1 -1
- data/lib/taskinator/visitor.rb +6 -0
- data/lib/taskinator/workflow.rb +36 -0
- data/lib/taskinator.rb +3 -2
- data/spec/examples/process_examples.rb +6 -9
- data/spec/examples/queue_adapter_examples.rb +2 -12
- data/spec/examples/task_examples.rb +5 -8
- data/spec/support/process_methods.rb +25 -0
- data/spec/support/task_methods.rb +13 -0
- data/spec/support/test_flows.rb +1 -3
- data/spec/support/test_instrumenter.rb +39 -0
- data/spec/support/test_queue.rb +0 -12
- data/spec/taskinator/definition_spec.rb +3 -5
- data/spec/taskinator/instrumentation_spec.rb +98 -0
- data/spec/taskinator/persistence_spec.rb +3 -41
- data/spec/taskinator/process_spec.rb +36 -34
- data/spec/taskinator/queues/delayed_job_spec.rb +0 -41
- data/spec/taskinator/queues/resque_spec.rb +0 -51
- data/spec/taskinator/queues/sidekiq_spec.rb +0 -50
- data/spec/taskinator/queues_spec.rb +1 -1
- data/spec/taskinator/task_spec.rb +96 -64
- data/spec/taskinator/test_flows_spec.rb +266 -1
- data/taskinator.gemspec +0 -21
- metadata +12 -173
- data/lib/taskinator/job_worker.rb +0 -17
- data/spec/taskinator/job_worker_spec.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 683a1ffedb432057d353d7ebbc31dff766bce83c
|
4
|
+
data.tar.gz: 92c78c8a6e2c87769269147557c9c2cb13be52fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9449a313b53581d06109e16d6f1a268a5f786848fc4d725e0852b773dbe99b1a68898a88c0d077bfb48590b976dbc4ca821e9207f20b50343f924493c35d9aa
|
7
|
+
data.tar.gz: 5c621a66e20dfef0f7800482ea5dd308c7470393537022791d3398a4f12c9350ca40a89267de82a149adcaf5c8561ae8b6aa732826ab85843e0f330cb701396f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
v0.3.0 - 28 Aug 2015
|
2
|
+
---
|
3
|
+
Added created_at and updated_at to process and task as attributes.
|
4
|
+
Improved serialization visitor to include an optional converter block for deserialization of attribute values.
|
5
|
+
Corrections to lazy loader logic and speed improvements.
|
6
|
+
Removed JobWorker as it's no longer necessary.
|
7
|
+
Improvements to instrumentation.
|
8
|
+
Removed workflow gem, and refactored process and task to implement the basics instead.
|
9
|
+
Several bug fixes.
|
10
|
+
|
1
11
|
v0.2.0 - 31 Jul 2015
|
2
12
|
---
|
3
13
|
Bug fix for `create_process_remotely` so that it returns the process uuid instead of nil.
|
data/Gemfile
CHANGED
@@ -3,5 +3,20 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in Taskinator.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
#
|
7
|
-
gem '
|
6
|
+
# queues
|
7
|
+
gem 'sidekiq' , '>= 3.5.0', :github => "mperham/sidekiq"
|
8
|
+
gem 'rspec-sidekiq' , '>= 2.1.0'
|
9
|
+
|
10
|
+
gem 'delayed_job' , '>= 4.0.0'
|
11
|
+
|
12
|
+
gem 'resque' , '>= 1.25.2'
|
13
|
+
gem 'resque_spec' , '>= 0.16.0'
|
14
|
+
|
15
|
+
# other
|
16
|
+
gem 'bundler' , '>= 1.6.0'
|
17
|
+
gem 'rake' , '>= 10.3.0'
|
18
|
+
gem 'activesupport' , '>= 4.0.0'
|
19
|
+
gem 'rspec'
|
20
|
+
gem 'coveralls' , '>= 0.7.0'
|
21
|
+
gem 'pry' , '>= 0.9.0'
|
22
|
+
gem 'pry-byebug' , '>= 1.3.0'
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
GIT
|
2
|
-
remote:
|
3
|
-
revision:
|
4
|
-
branch: master
|
2
|
+
remote: git://github.com/mperham/sidekiq.git
|
3
|
+
revision: b0cdd4cc868e7564b78ee34965067e025ec41689
|
5
4
|
specs:
|
6
|
-
|
5
|
+
sidekiq (3.5.0)
|
6
|
+
celluloid (~> 0.17.0)
|
7
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
8
|
+
json (~> 1.0)
|
9
|
+
redis (~> 3.2, >= 3.2.1)
|
10
|
+
redis-namespace (~> 1.5, >= 1.5.2)
|
7
11
|
|
8
12
|
PATH
|
9
13
|
remote: .
|
10
14
|
specs:
|
11
|
-
taskinator (0.
|
15
|
+
taskinator (0.3.0)
|
12
16
|
connection_pool (>= 2.2.0)
|
13
17
|
json (>= 1.8.2)
|
14
18
|
redis (>= 3.2.1)
|
@@ -25,7 +29,46 @@ GEM
|
|
25
29
|
tzinfo (~> 1.1)
|
26
30
|
byebug (5.0.0)
|
27
31
|
columnize (= 0.9.0)
|
28
|
-
celluloid (0.
|
32
|
+
celluloid (0.17.1.1)
|
33
|
+
bundler
|
34
|
+
celluloid-essentials
|
35
|
+
celluloid-extras
|
36
|
+
celluloid-fsm
|
37
|
+
celluloid-pool
|
38
|
+
celluloid-supervision
|
39
|
+
dotenv
|
40
|
+
nenv
|
41
|
+
rspec-logsplit (>= 0.1.2)
|
42
|
+
timers (~> 4.0.0)
|
43
|
+
celluloid-essentials (0.20.2)
|
44
|
+
bundler
|
45
|
+
dotenv
|
46
|
+
nenv
|
47
|
+
rspec-logsplit (>= 0.1.2)
|
48
|
+
timers (~> 4.0.0)
|
49
|
+
celluloid-extras (0.20.0)
|
50
|
+
bundler
|
51
|
+
dotenv
|
52
|
+
nenv
|
53
|
+
rspec-logsplit (>= 0.1.2)
|
54
|
+
timers (~> 4.0.0)
|
55
|
+
celluloid-fsm (0.20.0)
|
56
|
+
bundler
|
57
|
+
dotenv
|
58
|
+
nenv
|
59
|
+
rspec-logsplit (>= 0.1.2)
|
60
|
+
timers (~> 4.0.0)
|
61
|
+
celluloid-pool (0.20.0)
|
62
|
+
bundler
|
63
|
+
dotenv
|
64
|
+
nenv
|
65
|
+
rspec-logsplit (>= 0.1.2)
|
66
|
+
timers (~> 4.0.0)
|
67
|
+
celluloid-supervision (0.20.1)
|
68
|
+
bundler
|
69
|
+
dotenv
|
70
|
+
nenv
|
71
|
+
rspec-logsplit (>= 0.1.2)
|
29
72
|
timers (~> 4.0.0)
|
30
73
|
coderay (1.1.0)
|
31
74
|
columnize (0.9.0)
|
@@ -42,6 +85,7 @@ GEM
|
|
42
85
|
docile (1.1.5)
|
43
86
|
domain_name (0.5.24)
|
44
87
|
unf (>= 0.0.5, < 1.0.0)
|
88
|
+
dotenv (2.0.2)
|
45
89
|
hitimes (1.2.2)
|
46
90
|
http-cookie (1.0.2)
|
47
91
|
domain_name (~> 0.5)
|
@@ -49,9 +93,10 @@ GEM
|
|
49
93
|
json (1.8.3)
|
50
94
|
method_source (0.8.2)
|
51
95
|
mime-types (2.6.1)
|
52
|
-
minitest (5.
|
96
|
+
minitest (5.8.0)
|
53
97
|
mono_logger (1.1.0)
|
54
98
|
multi_json (1.11.2)
|
99
|
+
nenv (0.2.0)
|
55
100
|
netrc (0.10.3)
|
56
101
|
pry (0.10.1)
|
57
102
|
coderay (~> 1.1.0)
|
@@ -91,19 +136,14 @@ GEM
|
|
91
136
|
rspec-expectations (3.3.1)
|
92
137
|
diff-lcs (>= 1.2.0, < 2.0)
|
93
138
|
rspec-support (~> 3.3.0)
|
139
|
+
rspec-logsplit (0.1.3)
|
94
140
|
rspec-mocks (3.3.2)
|
95
141
|
diff-lcs (>= 1.2.0, < 2.0)
|
96
142
|
rspec-support (~> 3.3.0)
|
97
|
-
rspec-sidekiq (2.
|
143
|
+
rspec-sidekiq (2.1.0)
|
98
144
|
rspec (~> 3.0, >= 3.0.0)
|
99
145
|
sidekiq (>= 2.4.0)
|
100
146
|
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
147
|
simplecov (0.10.0)
|
108
148
|
docile (~> 1.1.0)
|
109
149
|
json (~> 1.8)
|
@@ -121,7 +161,7 @@ GEM
|
|
121
161
|
tilt (2.0.1)
|
122
162
|
timers (4.0.1)
|
123
163
|
hitimes
|
124
|
-
tins (1.
|
164
|
+
tins (1.6.0)
|
125
165
|
tzinfo (1.2.2)
|
126
166
|
thread_safe (~> 0.1)
|
127
167
|
unf (0.1.4)
|
@@ -144,7 +184,6 @@ DEPENDENCIES
|
|
144
184
|
resque (>= 1.25.2)
|
145
185
|
resque_spec (>= 0.16.0)
|
146
186
|
rspec
|
147
|
-
rspec-sidekiq (>= 2.
|
148
|
-
sidekiq (>= 3.
|
187
|
+
rspec-sidekiq (>= 2.1.0)
|
188
|
+
sidekiq (>= 3.5.0)!
|
149
189
|
taskinator!
|
150
|
-
workflow!
|
data/README.md
CHANGED
@@ -546,7 +546,7 @@ To monitor the state of the processes, use the `Taskinator::Api::Processes` clas
|
|
546
546
|
processes = Taskinator::Api::Processes.new
|
547
547
|
processes.each do |process|
|
548
548
|
# => output the unique process identifier and current state
|
549
|
-
puts [:process, process.uuid, process.current_state
|
549
|
+
puts [:process, process.uuid, process.current_state]
|
550
550
|
end
|
551
551
|
```
|
552
552
|
|
@@ -608,29 +608,33 @@ end
|
|
608
608
|
|
609
609
|
The following instrumentation events are issued:
|
610
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.
|
617
|
-
| `taskinator.process.
|
618
|
-
| `taskinator.process.
|
619
|
-
| `taskinator.
|
620
|
-
| `taskinator.
|
621
|
-
| `taskinator.
|
622
|
-
| `taskinator.
|
623
|
-
| `taskinator.
|
624
|
-
| `taskinator.
|
611
|
+
| Event | When |
|
612
|
+
|------------------------------------|-----------------------------------------------------------|
|
613
|
+
| `taskinator.process.created` | After a root process gets created |
|
614
|
+
| `taskinator.process.saved` | After a root process has been persisted to Redis |
|
615
|
+
| `taskinator.process.enqueued` | After a process or subprocess is enqueued for processing |
|
616
|
+
| `taskinator.process.processing` | When a process or subprocess is processing |
|
617
|
+
| `taskinator.process.paused` | When a process or subprocess is paused |
|
618
|
+
| `taskinator.process.resumed` | When a process or subprocess is resumed |
|
619
|
+
| `taskinator.process.completed` | After a process or subprocess has completed processing |
|
620
|
+
| `taskinator.process.cancelled` | After a process or subprocess has been cancelled |
|
621
|
+
| `taskinator.process.failed` | After a process or subprocess has failed |
|
622
|
+
| `taskinator.task.enqueued` | After a task has been enqueued |
|
623
|
+
| `taskinator.task.processing` | When a task is processing |
|
624
|
+
| `taskinator.task.completed` | After a task has completed |
|
625
|
+
| `taskinator.task.cancelled` | After a task has been cancelled |
|
626
|
+
| `taskinator.task.failed` | After a task has failed |
|
625
627
|
|
626
628
|
For all events, the data included contains the following information:
|
627
629
|
|
628
630
|
| Key | Value |
|
629
631
|
|--------------------------|-------------------------------------------------------|
|
632
|
+
| `:type` | The type name of the component reporting the event |
|
630
633
|
| `:process_uuid` | The UUID of the root process |
|
631
634
|
| `:process_options` | Options hash of the root process |
|
632
635
|
| `:uuid` | The UUID of the respective task, job or sub process |
|
633
|
-
| `:
|
636
|
+
| `:options` | Options hash of the component |
|
637
|
+
| `:state` | State of the component |
|
634
638
|
| `:percentage_completed` | The percentage of completed tasks |
|
635
639
|
| `:percentage_failed` | The percentage of failed tasks |
|
636
640
|
| `:percentage_cancelled` | The percentage of cancelled tasks |
|
@@ -48,7 +48,7 @@ module Taskinator
|
|
48
48
|
process = factory.call(self, options)
|
49
49
|
|
50
50
|
# this may take long... up to users definition
|
51
|
-
Taskinator.instrumenter.instrument('taskinator.process.created', :uuid => process.uuid) do
|
51
|
+
Taskinator.instrumenter.instrument('taskinator.process.created', :uuid => process.uuid, :state => :initial) do
|
52
52
|
Builder.new(process, self, *args).instance_eval(&block)
|
53
53
|
end
|
54
54
|
|
@@ -56,7 +56,7 @@ module Taskinator
|
|
56
56
|
unless subprocess
|
57
57
|
|
58
58
|
# instrument separately
|
59
|
-
Taskinator.instrumenter.instrument('taskinator.process.saved', :uuid => process.uuid) do
|
59
|
+
Taskinator.instrumenter.instrument('taskinator.process.saved', :uuid => process.uuid, :state => :initial) do
|
60
60
|
|
61
61
|
# this will visit "sub processes" and persist them too
|
62
62
|
process.save
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Taskinator
|
2
|
+
module Instrumentation
|
3
|
+
|
4
|
+
def instrument(event, payload={})
|
5
|
+
Taskinator.instrumenter.instrument(event, payload) do
|
6
|
+
yield
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# helper methods for instrumentation payloads
|
11
|
+
|
12
|
+
def enqueued_payload(additional={})
|
13
|
+
payload_for(:enqueued, additional)
|
14
|
+
end
|
15
|
+
|
16
|
+
def processing_payload(additional={})
|
17
|
+
payload_for(:processing, additional)
|
18
|
+
end
|
19
|
+
|
20
|
+
def paused_payload(additional={})
|
21
|
+
payload_for(:paused, additional)
|
22
|
+
end
|
23
|
+
|
24
|
+
def resumed_payload(additional={})
|
25
|
+
payload_for(:resumed, additional)
|
26
|
+
end
|
27
|
+
|
28
|
+
def completed_payload(additional={})
|
29
|
+
payload_for(:completed, additional)
|
30
|
+
end
|
31
|
+
|
32
|
+
def cancelled_payload(additional={})
|
33
|
+
payload_for(:cancelled, additional)
|
34
|
+
end
|
35
|
+
|
36
|
+
def failed_payload(exception, additional={})
|
37
|
+
payload_for(:failed, { :exception => exception.to_s, :backtrace => exception.backtrace }.merge(additional))
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def payload_for(state, additional={})
|
43
|
+
|
44
|
+
# need to cache here, since this method hits redis, so can't be part of multi statement following
|
45
|
+
process_key = self.process_key
|
46
|
+
|
47
|
+
tasks_count, processing_count, completed_count, cancelled_count, failed_count = Taskinator.redis do |conn|
|
48
|
+
conn.hmget process_key,
|
49
|
+
:tasks_count,
|
50
|
+
:tasks_processing,
|
51
|
+
:tasks_completed,
|
52
|
+
:tasks_cancelled,
|
53
|
+
:tasks_failed
|
54
|
+
end
|
55
|
+
|
56
|
+
tasks_count = tasks_count.to_f
|
57
|
+
|
58
|
+
return OpenStruct.new(
|
59
|
+
{
|
60
|
+
:type => self.class,
|
61
|
+
:process_uuid => process_uuid,
|
62
|
+
:process_options => process_options,
|
63
|
+
:uuid => uuid,
|
64
|
+
:options => options,
|
65
|
+
:state => state,
|
66
|
+
:percentage_failed => (tasks_count > 0) ? (failed_count.to_i / tasks_count) * 100.0 : 0.0,
|
67
|
+
:percentage_cancelled => (tasks_count > 0) ? (cancelled_count.to_i / tasks_count) * 100.0 : 0.0,
|
68
|
+
:percentage_processing => (tasks_count > 0) ? (processing_count.to_i / tasks_count) * 100.0 : 0.0,
|
69
|
+
:percentage_completed => (tasks_count > 0) ? (completed_count.to_i / tasks_count) * 100.0 : 0.0,
|
70
|
+
:instance => self
|
71
|
+
}.merge(additional)
|
72
|
+
).freeze
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -35,17 +35,6 @@ module Taskinator
|
|
35
35
|
"taskinator:#{base_key}:#{uuid}"
|
36
36
|
end
|
37
37
|
|
38
|
-
# retrieves the workflow state for the given identifier
|
39
|
-
# this prevents to need to load the entire object when
|
40
|
-
# querying for the status of an instance
|
41
|
-
def state_for(uuid)
|
42
|
-
key = key_for(uuid)
|
43
|
-
state = Taskinator.redis do |conn|
|
44
|
-
conn.hget(key, :state) || 'initial'
|
45
|
-
end
|
46
|
-
state.to_sym
|
47
|
-
end
|
48
|
-
|
49
38
|
# fetches the instance for given identifier
|
50
39
|
# optionally, provide a hash to use for the instance cache
|
51
40
|
# this argument is defaulted, so top level callers don't
|
@@ -68,10 +57,11 @@ module Taskinator
|
|
68
57
|
visitor = RedisSerializationVisitor.new(conn, self).visit
|
69
58
|
conn.hmset(
|
70
59
|
Taskinator::Process.key_for(uuid),
|
71
|
-
:tasks_count,
|
72
|
-
:tasks_failed,
|
73
|
-
:
|
74
|
-
:
|
60
|
+
:tasks_count, visitor.task_count,
|
61
|
+
:tasks_failed, 0,
|
62
|
+
:tasks_processing, 0,
|
63
|
+
:tasks_completed, 0,
|
64
|
+
:tasks_cancelled, 0,
|
75
65
|
)
|
76
66
|
true
|
77
67
|
end
|
@@ -99,17 +89,32 @@ module Taskinator
|
|
99
89
|
# this method is called from the workflow gem
|
100
90
|
def load_workflow_state
|
101
91
|
state = Taskinator.redis do |conn|
|
102
|
-
conn.hget(self.key, :state)
|
92
|
+
conn.hget(self.key, :state) || 'initial'
|
103
93
|
end
|
104
|
-
|
94
|
+
state.to_sym
|
105
95
|
end
|
106
96
|
|
107
97
|
# persists the workflow state
|
108
98
|
# this method is called from the workflow gem
|
109
99
|
def persist_workflow_state(new_state)
|
100
|
+
@updated_at = Time.now.utc
|
110
101
|
Taskinator.redis do |conn|
|
111
|
-
|
102
|
+
process_key = self.process_key
|
103
|
+
conn.multi do
|
104
|
+
conn.hmset(
|
105
|
+
self.key,
|
106
|
+
:state, new_state,
|
107
|
+
:updated_at, @updated_at
|
108
|
+
)
|
109
|
+
|
110
|
+
# also update the "root" process
|
111
|
+
conn.hset(
|
112
|
+
process_key,
|
113
|
+
:updated_at, @updated_at
|
114
|
+
)
|
115
|
+
end
|
112
116
|
end
|
117
|
+
new_state
|
113
118
|
end
|
114
119
|
|
115
120
|
# persists the error information
|
@@ -121,7 +126,8 @@ module Taskinator
|
|
121
126
|
self.key,
|
122
127
|
:error_type, error.class.name,
|
123
128
|
:error_message, error.message,
|
124
|
-
:error_backtrace, JSON.generate(error.backtrace || [])
|
129
|
+
:error_backtrace, JSON.generate(error.backtrace || []),
|
130
|
+
:updated_at, Time.now.utc
|
125
131
|
)
|
126
132
|
end
|
127
133
|
end
|
@@ -133,7 +139,7 @@ module Taskinator
|
|
133
139
|
error_type, error_message, error_backtrace =
|
134
140
|
conn.hmget(self.key, :error_type, :error_message, :error_backtrace)
|
135
141
|
|
136
|
-
[error_type, error_message, JSON.parse(error_backtrace)]
|
142
|
+
[error_type, error_message, JSON.parse(error_backtrace || '[]')]
|
137
143
|
end
|
138
144
|
end
|
139
145
|
|
@@ -149,19 +155,24 @@ module Taskinator
|
|
149
155
|
%w(
|
150
156
|
failed
|
151
157
|
cancelled
|
158
|
+
processing
|
152
159
|
completed
|
153
160
|
).each do |status|
|
154
161
|
|
155
162
|
define_method "count_#{status}" do
|
156
163
|
count = Taskinator.redis do |conn|
|
157
|
-
conn.hget self.process_key, status
|
164
|
+
conn.hget self.process_key, "tasks_#{status}"
|
158
165
|
end
|
159
166
|
count.to_i
|
160
167
|
end
|
161
168
|
|
162
169
|
define_method "incr_#{status}" do
|
163
170
|
Taskinator.redis do |conn|
|
164
|
-
|
171
|
+
process_key = self.process_key
|
172
|
+
conn.multi do
|
173
|
+
conn.hincrby process_key, "tasks_#{status}", 1
|
174
|
+
conn.hset process_key, :updated_at, Time.now.utc
|
175
|
+
end
|
165
176
|
end
|
166
177
|
end
|
167
178
|
|
@@ -183,34 +194,6 @@ module Taskinator
|
|
183
194
|
end
|
184
195
|
end
|
185
196
|
|
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
|
-
|
214
197
|
end
|
215
198
|
|
216
199
|
class RedisSerializationVisitor < Visitor::Base
|
@@ -244,6 +227,9 @@ module Taskinator
|
|
244
227
|
# add the process uuid and root key, for easy access later!
|
245
228
|
@hmset += [:process_uuid, @root.uuid]
|
246
229
|
|
230
|
+
# add the default state
|
231
|
+
@hmset += [:state, :initial]
|
232
|
+
|
247
233
|
# NB: splat args
|
248
234
|
@conn.hmset(*@hmset)
|
249
235
|
|
@@ -259,7 +245,6 @@ module Taskinator
|
|
259
245
|
end
|
260
246
|
|
261
247
|
def visit_tasks(tasks)
|
262
|
-
@hmset += [:task_count, tasks.count] # not used currently, but for informational purposes
|
263
248
|
tasks.each do |task|
|
264
249
|
RedisSerializationVisitor.new(@conn, task, @base_visitor).visit
|
265
250
|
@conn.rpush "#{@key}:tasks", task.uuid
|
@@ -272,6 +257,14 @@ module Taskinator
|
|
272
257
|
@hmset += [attribute, value] if value
|
273
258
|
end
|
274
259
|
|
260
|
+
def visit_attribute_time(attribute)
|
261
|
+
visit_attribute(attribute)
|
262
|
+
end
|
263
|
+
|
264
|
+
def visit_attribute_enum(attribute, type)
|
265
|
+
visit_attribute(attribute)
|
266
|
+
end
|
267
|
+
|
275
268
|
def visit_process_reference(attribute)
|
276
269
|
process = @instance.send(attribute)
|
277
270
|
@hmset += [attribute, process.uuid] if process
|
@@ -374,7 +367,30 @@ module Taskinator
|
|
374
367
|
|
375
368
|
def visit_attribute(attribute)
|
376
369
|
value = @attribute_values[attribute]
|
377
|
-
|
370
|
+
if value
|
371
|
+
# converted block given?
|
372
|
+
if block_given?
|
373
|
+
@instance.instance_variable_set("@#{attribute}", yield(value))
|
374
|
+
else
|
375
|
+
@instance.instance_variable_set("@#{attribute}", value)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def visit_attribute_time(attribute)
|
381
|
+
visit_attribute(attribute) do |value|
|
382
|
+
Time.parse(value)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
# NB: assumes the enum type's members have integer values!
|
387
|
+
def visit_attribute_enum(attribute, type)
|
388
|
+
visit_attribute(attribute) do |value|
|
389
|
+
const_value = type.constants.select {|c| type.const_get(c) == value.to_i }.first
|
390
|
+
const_value ?
|
391
|
+
type.const_get(const_value) :
|
392
|
+
(defined?(type::Default) ? type::Default : nil)
|
393
|
+
end
|
378
394
|
end
|
379
395
|
|
380
396
|
def visit_type(attribute)
|
@@ -405,11 +421,11 @@ module Taskinator
|
|
405
421
|
# arbitrary instance to perform it's work
|
406
422
|
#
|
407
423
|
def lazy_instance_for(base, uuid)
|
408
|
-
type
|
409
|
-
conn.
|
424
|
+
type = Taskinator.redis do |conn|
|
425
|
+
conn.hget(base.key_for(uuid), :type)
|
410
426
|
end
|
411
427
|
klass = Kernel.const_get(type)
|
412
|
-
LazyLoader.new(klass, uuid,
|
428
|
+
LazyLoader.new(klass, uuid, @instance_cache)
|
413
429
|
end
|
414
430
|
end
|
415
431
|
|
@@ -424,17 +440,12 @@ module Taskinator
|
|
424
440
|
# E.g. this is useful for tasks which refer to their parent processes
|
425
441
|
#
|
426
442
|
|
427
|
-
def initialize(type, uuid,
|
443
|
+
def initialize(type, uuid, instance_cache={})
|
428
444
|
@type = type
|
429
445
|
@uuid = uuid
|
430
|
-
@process_uuid = process_uuid
|
431
446
|
@instance_cache = instance_cache
|
432
447
|
end
|
433
448
|
|
434
|
-
# shadows the real methods, but will be the same!
|
435
|
-
attr_reader :process_uuid
|
436
|
-
attr_reader :uuid
|
437
|
-
|
438
449
|
def __getobj__
|
439
450
|
# only fetch the object as needed
|
440
451
|
# and memoize for subsequent calls
|