queue_dispatcher 2.3.0 → 2.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/queue_dispatcher/acts_as_task.rb +39 -2
- data/lib/queue_dispatcher/acts_as_task_queue.rb +25 -11
- data/lib/queue_dispatcher/version.rb +1 -1
- data/queue_dispatcher.gemspec +9 -8
- data/script/queue_worker_dispatcher +21 -4
- metadata +22 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b13a171b35ddf613aa446a4c918a1e994ec24e3
|
4
|
+
data.tar.gz: 0e831f41b6d5815e4418946cb7b6a924444a360b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 877e9ea6a9313f4b73c3d15f0cfdcfa07d7b6524f7b84df26b9765a986af0124852bdfcbe321301a4dc2dd8bd5ee1234bf314d8ac71111c8dac482ec49066615
|
7
|
+
data.tar.gz: 9319b0f7053f7a1e712d6e458ad12cbc55830a93edbe1442dabf5ea6224cdaadbb05ca7155796d20296b08de9b79b5fb853afef59b4f003379774273daa340d4
|
data/CHANGELOG.md
ADDED
@@ -40,6 +40,15 @@ module QueueDispatcher
|
|
40
40
|
belongs_to :dependent_task, :class_name => '#{self.name}'
|
41
41
|
}
|
42
42
|
end
|
43
|
+
|
44
|
+
|
45
|
+
[:success, :error].each do |state|
|
46
|
+
define_method("on_#{state}") do |*method_names|
|
47
|
+
method_names.each do |method_name|
|
48
|
+
eval "(@#{state}_callback_chain ||= []) << method_name"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
43
52
|
end
|
44
53
|
|
45
54
|
|
@@ -47,6 +56,13 @@ module QueueDispatcher
|
|
47
56
|
def acts_as_task_config
|
48
57
|
@acts_as_task_config
|
49
58
|
end
|
59
|
+
|
60
|
+
|
61
|
+
[:success, :error].each do |state|
|
62
|
+
define_method("#{state}_callback_chain") do
|
63
|
+
eval("@#{state}_callback_chain") || []
|
64
|
+
end
|
65
|
+
end
|
50
66
|
end
|
51
67
|
|
52
68
|
|
@@ -74,7 +90,7 @@ module QueueDispatcher
|
|
74
90
|
|
75
91
|
|
76
92
|
# This method updates the task state according to the return code of their corresponding command and removes it from the task_queue
|
77
|
-
def
|
93
|
+
def update_state_and_exec_callbacks(result, remove_from_queue = false, logger = nil)
|
78
94
|
rc = output = error_msg = nil
|
79
95
|
|
80
96
|
if result.methods.map(&:to_sym).include?(:rc) && result.methods.map(&:to_sym).include?(:output) && result.methods.map(&:to_sym).include?(:error_msg)
|
@@ -90,21 +106,25 @@ module QueueDispatcher
|
|
90
106
|
end
|
91
107
|
|
92
108
|
output ||= ''
|
109
|
+
successful = result.methods.map(&:to_sym).include?(:successful?) ? result.successful? : rc.nil? || rc == 0
|
93
110
|
|
94
|
-
if
|
111
|
+
if successful
|
95
112
|
self.update_attributes :state => 'successful',
|
96
113
|
:perc_finished => 100,
|
97
114
|
:message => output.truncate(10256),
|
98
115
|
:result => result
|
116
|
+
success_callbacks(logger)
|
99
117
|
else
|
100
118
|
self.update_attributes :state => 'error',
|
101
119
|
:error_msg => error_msg,
|
102
120
|
:message => output.truncate(10256),
|
103
121
|
:result => result
|
122
|
+
error_callbacks(logger)
|
104
123
|
end
|
105
124
|
|
106
125
|
self.update_attributes :task_queue_id => nil if remove_from_queue
|
107
126
|
|
127
|
+
|
108
128
|
rc
|
109
129
|
end
|
110
130
|
|
@@ -216,6 +236,23 @@ module QueueDispatcher
|
|
216
236
|
payload.send(method_name, *args)
|
217
237
|
end
|
218
238
|
|
239
|
+
private
|
240
|
+
|
241
|
+
# Callbacks
|
242
|
+
[:success, :error].each do |state|
|
243
|
+
define_method("#{state}_callbacks") do |logger|
|
244
|
+
eval("self.class.#{state}_callback_chain").each do |method_name|
|
245
|
+
begin
|
246
|
+
send method_name
|
247
|
+
rescue => exception
|
248
|
+
backtrace = exception.backtrace.join("\n ")
|
249
|
+
msg = "Fatal error in method '#{method_name}', while executing it in #{state}_callbacks: #{$!}\n #{backtrace}"
|
250
|
+
logger.send(:error, msg) if logger
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
219
256
|
end
|
220
257
|
end
|
221
258
|
end
|
@@ -52,6 +52,26 @@ module QueueDispatcher
|
|
52
52
|
end
|
53
53
|
|
54
54
|
|
55
|
+
# Check if a certain PID is still running and is a ruby process
|
56
|
+
def pid_running?(pid)
|
57
|
+
ps = pid ? Sys::ProcTable.ps(pid) : nil
|
58
|
+
if ps
|
59
|
+
# Asume, that if the command of the 'ps'-output is 'ruby', the process is still running
|
60
|
+
ps.comm == 'ruby'
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Check if QueueDispatcher is running.
|
68
|
+
def qd_running?
|
69
|
+
running = false
|
70
|
+
TaskQueue.where(state: 'heartbeat').each { |tq| running = true if tq.updated_at > 1.minute.ago }
|
71
|
+
running
|
72
|
+
end
|
73
|
+
|
74
|
+
|
55
75
|
# Are there any running task_queues?
|
56
76
|
def any_running?
|
57
77
|
running = false
|
@@ -66,7 +86,7 @@ module QueueDispatcher
|
|
66
86
|
|
67
87
|
transaction do
|
68
88
|
# Find next task_queue which is not running and not in state error
|
69
|
-
order(:id).lock(true).all.each { |tq| task_queue = tq unless task_queue || tq.pid_running? || tq.state == 'error' }
|
89
|
+
order(:id).lock(true).all.each { |tq| task_queue = tq unless task_queue || tq.pid_running? || tq.state == 'error' || tq.state == 'heartbeat' }
|
70
90
|
|
71
91
|
# Update pid inside the atomic transaction to be sure, the next call of this method will not give the same queue a second time
|
72
92
|
task_queue.update_attribute :pid, $$ if task_queue
|
@@ -179,13 +199,7 @@ module QueueDispatcher
|
|
179
199
|
|
180
200
|
# Return true, if the command of the process with pid 'self.pid' is 'ruby'
|
181
201
|
def pid_running?
|
182
|
-
|
183
|
-
if ps
|
184
|
-
# Asume, that if the command of the 'ps'-output is 'ruby', the process is still running
|
185
|
-
ps.comm == 'ruby'
|
186
|
-
else
|
187
|
-
false
|
188
|
-
end
|
202
|
+
self.class.pid_running?(self.pid)
|
189
203
|
end
|
190
204
|
|
191
205
|
|
@@ -276,7 +290,7 @@ module QueueDispatcher
|
|
276
290
|
task_queue.update_attribute :state, 'running'
|
277
291
|
|
278
292
|
# Set logger in engine
|
279
|
-
@engine.logger = @logger if defined?
|
293
|
+
@engine.logger = @logger if defined?(@engine) && @engine.methods.include?(:logger=)
|
280
294
|
log :msg => "#{name}: Starting TaskQueue #{task_queue.id}...", :print_log => print_log
|
281
295
|
|
282
296
|
# Init. Pop first task from queue, to show init_queue-state
|
@@ -328,7 +342,7 @@ module QueueDispatcher
|
|
328
342
|
end
|
329
343
|
|
330
344
|
# Change task state according to the return code and remove it from the queue
|
331
|
-
task.
|
345
|
+
task.update_state_and_exec_callbacks(result, false, logger)
|
332
346
|
cleanup_locks_after_error_for task
|
333
347
|
task.update_attribute :task_queue_id, nil unless acts_as_task_queue_config.leave_finished_tasks_in_queue
|
334
348
|
log :msg => "#{name}: Task #{task.id} (#{task.payload.class.name}.#{task.method_name}) finished with state '#{task.state}'.", :print_log => print_log
|
@@ -378,7 +392,7 @@ module QueueDispatcher
|
|
378
392
|
backtrace = exception.backtrace.join("\n ")
|
379
393
|
log :msg => "Fatal error in method 'run!': #{$!}\n #{backtrace}", :sev => :error, :print_log => print_log
|
380
394
|
puts "Fatal error in method 'run!': #{$!}\n#{backtrace}"
|
381
|
-
task.
|
395
|
+
task.update_state_and_exec_callbacks(QueueDispatcher::RcAndMsg.bad_rc("Fatal error: #{$!}"), false, logger) if task
|
382
396
|
cleanup_locks_after_error_for task if task
|
383
397
|
task.update_attributes state: 'error' if task && task.state != 'finished'
|
384
398
|
ensure
|
data/queue_dispatcher.gemspec
CHANGED
@@ -7,17 +7,18 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = QueueDispatcher::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Philip Kurmann"]
|
10
|
-
s.email = ["
|
11
|
-
s.
|
10
|
+
s.email = ["info@inwork.ch"]
|
11
|
+
s.license = "MIT"
|
12
|
+
s.homepage = "https://inwork.github.io/queue_dispatcher/"
|
12
13
|
s.summary = %q{This Gem installs a queue dispatcher for handling asynchronous tasks}
|
13
14
|
s.description = %q{Queue_Dispatcher executes asynchronous tasks in the background.}
|
14
15
|
|
15
|
-
s.add_dependency 'sys-proctable', '
|
16
|
-
s.add_dependency 'deadlock_retry'
|
17
|
-
s.add_dependency 'spawnling'
|
18
|
-
s.add_dependency 'haml'
|
19
|
-
s.add_dependency 'will_paginate'
|
20
|
-
s.add_dependency 'jquery-rails'
|
16
|
+
s.add_dependency 'sys-proctable', '~> 0.9'
|
17
|
+
s.add_dependency 'deadlock_retry', '~> 0'
|
18
|
+
s.add_dependency 'spawnling', '~> 0'
|
19
|
+
s.add_dependency 'haml', '~> 0'
|
20
|
+
s.add_dependency 'will_paginate', '~> 0'
|
21
|
+
s.add_dependency 'jquery-rails', '~> 0'
|
21
22
|
|
22
23
|
s.files = `git ls-files`.split("\n")
|
23
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -35,7 +35,8 @@ $daemon = {
|
|
35
35
|
:background => false, # background mode
|
36
36
|
:work => true, # daemon work flag
|
37
37
|
:logger_msg_prefix => nil, # Prefix for logging
|
38
|
-
:worker_pids => []
|
38
|
+
:worker_pids => [], # Remember PIDs
|
39
|
+
:heartbeat_task_queue_id => nil # Remember ID of the Heartbeat-TaskQueue
|
39
40
|
}
|
40
41
|
|
41
42
|
$worker = {
|
@@ -74,6 +75,7 @@ end
|
|
74
75
|
|
75
76
|
# Clean up before a daemon terminates
|
76
77
|
def daemon_clean_up
|
78
|
+
TaskQueue.where(id: $daemon[:heartbeat_task_queue_id]).destroy_all
|
77
79
|
File.delete($daemon[:pid_file])
|
78
80
|
end
|
79
81
|
|
@@ -137,14 +139,15 @@ def daemon_start
|
|
137
139
|
|
138
140
|
# Asume, that if the command of the 'ps'-output is 'ruby', the process is still running
|
139
141
|
if ps && (ps.comm == 'ruby')
|
140
|
-
daemon_log :msg =>
|
142
|
+
daemon_log :msg => 'Process already running!', :sev => :error
|
141
143
|
exit
|
142
144
|
else
|
143
145
|
File.delete($daemon[:pid_file])
|
144
146
|
end
|
145
147
|
end
|
146
148
|
|
147
|
-
|
149
|
+
# Start daemon
|
150
|
+
daemon_log :msg => 'Starting process...'
|
148
151
|
if $daemon[:background]
|
149
152
|
Spawnling.new { daemon_runner }
|
150
153
|
else
|
@@ -153,11 +156,25 @@ def daemon_start
|
|
153
156
|
end
|
154
157
|
|
155
158
|
|
159
|
+
# update heartbeat
|
160
|
+
def daemon_update_heartbeat
|
161
|
+
hb_tq = TaskQueue.find_by(id: $daemon[:heartbeat_task_queue_id])
|
162
|
+
if hb_tq
|
163
|
+
hb_tq.touch
|
164
|
+
else
|
165
|
+
hb_tq = TaskQueue.create(name: 'QD_HeartBeat', state: 'heartbeat', pid: Process.pid)
|
166
|
+
$daemon[:heartbeat_task_queue_id] = hb_tq.id
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
|
156
171
|
# Start an amount of workers
|
157
172
|
def spawn_and_monitor_workers
|
158
173
|
daemon_log :msg => "Spawning #{$daemon[:worker_count]} workers..."
|
159
174
|
|
160
175
|
while $daemon[:work]
|
176
|
+
daemon_update_heartbeat
|
177
|
+
|
161
178
|
# (Re)start workers
|
162
179
|
while $daemon[:worker_pids].count < $daemon[:worker_count] do
|
163
180
|
sp = Spawnling.new(:argv => $worker[:process_prefix]) do
|
@@ -197,7 +214,7 @@ def worker_runner
|
|
197
214
|
if $worker[:task_queue]
|
198
215
|
# Set Process Name and execute tasks
|
199
216
|
$0 = "#{$worker[:process_prefix]}_#{$worker[:task_queue].id}"
|
200
|
-
$worker[:task_queue].run!(:print_log => ! $daemon[:background])
|
217
|
+
$worker[:task_queue].run!(:print_log => ! $daemon[:background], logger: @logger)
|
201
218
|
else
|
202
219
|
# Set Process Name and sleep
|
203
220
|
$0 = "#{$worker[:process_prefix]}_idle"
|
metadata
CHANGED
@@ -1,107 +1,108 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: queue_dispatcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3
|
4
|
+
version: 2.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Philip Kurmann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sys-proctable
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.9
|
19
|
+
version: '0.9'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.9
|
26
|
+
version: '0.9'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: deadlock_retry
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: spawnling
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: haml
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: will_paginate
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: jquery-rails
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: Queue_Dispatcher executes asynchronous tasks in the background.
|
98
98
|
email:
|
99
|
-
-
|
99
|
+
- info@inwork.ch
|
100
100
|
executables: []
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
104
|
- ".gitignore"
|
105
|
+
- CHANGELOG.md
|
105
106
|
- Gemfile
|
106
107
|
- LICENSE
|
107
108
|
- README.rdoc
|
@@ -151,8 +152,9 @@ files:
|
|
151
152
|
- lib/tasks/queue_dispatcher.rake
|
152
153
|
- queue_dispatcher.gemspec
|
153
154
|
- script/queue_worker_dispatcher
|
154
|
-
homepage:
|
155
|
-
licenses:
|
155
|
+
homepage: https://inwork.github.io/queue_dispatcher/
|
156
|
+
licenses:
|
157
|
+
- MIT
|
156
158
|
metadata: {}
|
157
159
|
post_install_message:
|
158
160
|
rdoc_options: []
|
@@ -170,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
172
|
version: '0'
|
171
173
|
requirements: []
|
172
174
|
rubyforge_project:
|
173
|
-
rubygems_version: 2.
|
175
|
+
rubygems_version: 2.4.5
|
174
176
|
signing_key:
|
175
177
|
specification_version: 4
|
176
178
|
summary: This Gem installs a queue dispatcher for handling asynchronous tasks
|