resque-sliders 0.0.4 → 0.0.5
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.
- data/lib/resque-sliders/commander.rb +1 -6
- data/lib/resque-sliders/helpers.rb +24 -8
- data/lib/resque-sliders/kewatcher.rb +49 -30
- data/lib/resque-sliders/server/public/css/sliders.css +2 -0
- data/lib/resque-sliders/server/public/js/sliders.js +34 -8
- data/lib/resque-sliders/server/views/index.erb +3 -9
- data/lib/resque-sliders/server.rb +29 -2
- data/lib/resque-sliders/version.rb +1 -1
- metadata +4 -4
@@ -15,7 +15,7 @@ module Resque
|
|
15
15
|
|
16
16
|
# Return Array of currently online hosts
|
17
17
|
def hosts
|
18
|
-
@host_status.keys.select { |x| x unless x.split(':').last
|
18
|
+
@host_status.keys.select { |x| x unless %w(reload pause stop).include? x.split(':').last }.map { |x| x.split(':').first }.uniq.sort
|
19
19
|
end
|
20
20
|
|
21
21
|
# Array of all hosts (current + stale)
|
@@ -62,11 +62,6 @@ module Resque
|
|
62
62
|
redis_del_hash("#{key_prefix}:#{host}", queue)
|
63
63
|
end
|
64
64
|
|
65
|
-
# Sets reload flag on field of config_key to reload host's KEWatcher
|
66
|
-
def reload(host)
|
67
|
-
redis_set_hash(host_config_key, "#{host}:reload", 1)
|
68
|
-
end
|
69
|
-
|
70
65
|
end
|
71
66
|
end
|
72
67
|
end
|
@@ -36,15 +36,28 @@ module Resque
|
|
36
36
|
redis_set_hash(host_config_key, "#{@hostname}:#{setting}", value)
|
37
37
|
end
|
38
38
|
|
39
|
+
def unregister_setting(setting)
|
40
|
+
redis_del_hash(host_config_key, "#{@hostname}:#{setting}")
|
41
|
+
end
|
39
42
|
|
40
43
|
# Signal Checking
|
41
44
|
|
42
|
-
|
43
45
|
# Gets signal field in redis config_key for this host. Don't call directly
|
44
46
|
def check_signal(host)
|
45
47
|
sig = caller[0][/`([^']*)'/, 1].gsub('?', '')
|
46
48
|
raise 'Dont call me that' unless %w(reload pause stop).include?(sig)
|
47
|
-
|
49
|
+
if @hostname
|
50
|
+
# if instance variable set from running daemon, make a freshy
|
51
|
+
redis_get_hash_field(host_config_key, "#{@hostname}:#{sig}").to_i == 1 ? true : false
|
52
|
+
else
|
53
|
+
# otherwise cache call in a Hash
|
54
|
+
@host_signal_map ||= {}
|
55
|
+
@host_signal_map[host] ||= {}
|
56
|
+
unless @host_signal_map[host].has_key?(sig)
|
57
|
+
@host_signal_map[host] = {sig => redis_get_hash_field(host_config_key, "#{host}:#{sig}").to_i == 1 ? true : false}.update(@host_signal_map[host])
|
58
|
+
end
|
59
|
+
@host_signal_map[host][sig]
|
60
|
+
end
|
48
61
|
end
|
49
62
|
|
50
63
|
def reload?(host)
|
@@ -59,12 +72,15 @@ module Resque
|
|
59
72
|
check_signal(host)
|
60
73
|
end
|
61
74
|
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
75
|
+
# Set signal key given signal, host
|
76
|
+
def set_signal_flag(sig, host=@hostname)
|
77
|
+
@hostname ||= host
|
78
|
+
if sig == 'play'
|
79
|
+
%w(pause stop).each { |x| unregister_setting(x) }
|
80
|
+
else
|
81
|
+
register_setting(sig, 1)
|
82
|
+
end
|
83
|
+
end
|
68
84
|
|
69
85
|
end
|
70
86
|
end
|
@@ -51,26 +51,26 @@ module Resque
|
|
51
51
|
count += 1
|
52
52
|
log! ["watching:", @pids.keys.join(', '), "(#{@pids.keys.length})"].delete_if { |x| x == (nil || '') }.join(' ') if count % (10 / interval) == 1
|
53
53
|
|
54
|
+
tick = count % (20 / interval) == 1 ? true : false
|
55
|
+
(log! "checking signals..."; check_signals) if tick
|
54
56
|
if not (paused? || shutdown?)
|
55
|
-
if
|
56
|
-
# do first and also about every 20 seconds so we can throttle calls to redis
|
57
|
-
queue_diff!
|
58
|
-
signal_hup if check_reload and not count == 1
|
59
|
-
procline @pids.keys.join(', ')
|
60
|
-
end
|
57
|
+
queue_diff! if tick # do first and also about every 20 seconds so we can throttle calls to redis
|
61
58
|
|
62
59
|
while @pids.keys.length < @max_children && (@need_queues.length > 0 || @dead_queues.length > 0)
|
63
60
|
queue = @dead_queues.shift || @need_queues.shift
|
64
61
|
@pids.store(fork { exec("rake#{' -f ' + @rakefile if @rakefile}#{' environment' if ENV['RAILS_ENV']} resque:work QUEUE=#{queue}") }, queue) # store offset if linux fork() ?
|
65
|
-
procline
|
62
|
+
procline
|
66
63
|
end
|
67
64
|
end
|
68
65
|
|
69
66
|
register_setting('current_children', @pids.keys.length) if old != @pids.length
|
70
67
|
old = @pids.length
|
71
68
|
|
69
|
+
procline if tick
|
70
|
+
|
72
71
|
sleep(interval) # microsleep
|
73
72
|
kill_zombies! # need to cleanup ones we've killed
|
73
|
+
|
74
74
|
@pids.keys.each do |pid|
|
75
75
|
begin
|
76
76
|
# check to see if pid is running, by waiting for it, with a timeout
|
@@ -97,15 +97,6 @@ module Resque
|
|
97
97
|
|
98
98
|
private
|
99
99
|
|
100
|
-
def check_reload
|
101
|
-
(unregister_setting('reload'); return true) if reload?(@hostname)
|
102
|
-
false
|
103
|
-
end
|
104
|
-
|
105
|
-
def unregister_setting(setting)
|
106
|
-
redis_del_hash(host_config_key, "#{@hostname}:#{setting}")
|
107
|
-
end
|
108
|
-
|
109
100
|
# Forces (via signal QUIT) any KEWatcher process running, located by ps and grep
|
110
101
|
def restart_running!
|
111
102
|
count = 0
|
@@ -126,6 +117,7 @@ module Resque
|
|
126
117
|
log! "Found RAILS_ENV=#{ENV['RAILS_ENV']}" if ENV['RAILS_ENV']
|
127
118
|
enable_gc_optimizations
|
128
119
|
register_signal_handlers
|
120
|
+
clean_signal_settings
|
129
121
|
register_setting('max_children', @max_children)
|
130
122
|
log! "Registered Max Children with Redis"
|
131
123
|
$stdout.sync = true
|
@@ -143,10 +135,10 @@ module Resque
|
|
143
135
|
|
144
136
|
begin
|
145
137
|
trap('QUIT') { shutdown! }
|
146
|
-
trap('HUP') { signal_hup }
|
147
|
-
trap('USR1') { signal_usr1 }
|
148
|
-
trap('USR2') { signal_usr2 }
|
149
|
-
trap('CONT') { signal_cont }
|
138
|
+
trap('HUP') { log "HUP received; purging children..."; signal_hup }
|
139
|
+
trap('USR1') { log "USR1 received; killing little children..."; set_signal_flag('stop'); signal_usr1 }
|
140
|
+
trap('USR2') { log "USR2 received; not making babies"; set_signal_flag('pause'); signal_usr2 }
|
141
|
+
trap('CONT') { log "CONT received; making babies..."; set_signal_flag('play'); signal_cont }
|
150
142
|
rescue ArgumentError
|
151
143
|
warn "Signals QUIT, USR1, USR2, and/or CONT not supported."
|
152
144
|
end
|
@@ -154,8 +146,34 @@ module Resque
|
|
154
146
|
log! "Registered signals"
|
155
147
|
end
|
156
148
|
|
157
|
-
def
|
158
|
-
|
149
|
+
def clean_signal_settings
|
150
|
+
%w(pause stop reload).each { |x| unregister_setting(x) }
|
151
|
+
end
|
152
|
+
|
153
|
+
# Check signals, do appropriate thing
|
154
|
+
def check_signals
|
155
|
+
if reload?(@hostname)
|
156
|
+
log ' -> RELOAD from web-ui'
|
157
|
+
signal_hup
|
158
|
+
@dead_queues = Array.new # clear killed queues because we're reloading in same tick as queue_diff!
|
159
|
+
elsif stop?(@hostname)
|
160
|
+
log ' -> STOPPED from web-ui' if not paused? or @pids.keys.length > 0
|
161
|
+
signal_usr1
|
162
|
+
elsif pause?(@hostname)
|
163
|
+
log ' -> PAUSED from web-ui' unless paused?
|
164
|
+
signal_usr2
|
165
|
+
else
|
166
|
+
log! ' -> Continuing; no signal found'
|
167
|
+
@dead_queues = Array.new if paused? # clear killed queues when entering out of pause automatically, in same tick will refresh
|
168
|
+
signal_cont
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def procline(status=nil)
|
173
|
+
status ||= 'stopped' if paused? and @pids.keys.empty?
|
174
|
+
status ||= 'paused' if paused?
|
175
|
+
status = "#{[@pids.keys.length,status].compact.join('-')}" unless status == 'stopped'
|
176
|
+
$0 = "KEWatcher (#{status}): #{@pids.keys.join(', ')}"
|
159
177
|
log! $0
|
160
178
|
end
|
161
179
|
|
@@ -210,18 +228,18 @@ module Resque
|
|
210
228
|
[to_start, to_kill] # return whats left
|
211
229
|
end
|
212
230
|
|
231
|
+
# removes pid completely, ignores its queues
|
213
232
|
def remove!(pid)
|
214
|
-
# removes pid completely, ignores its queues
|
215
233
|
kill_child pid
|
216
234
|
@pids.delete(pid)
|
217
|
-
procline
|
235
|
+
procline
|
218
236
|
end
|
219
237
|
|
238
|
+
# remove pid, and respawn same queues
|
220
239
|
def remove(pid)
|
221
|
-
# remove pid, and respawn same queues
|
222
240
|
@dead_queues.unshift(@pids[pid]) # keep track of queues that pid was running, put it at front of list
|
223
241
|
@pids.delete(pid)
|
224
|
-
procline
|
242
|
+
procline
|
225
243
|
end
|
226
244
|
|
227
245
|
def shutdown!
|
@@ -242,25 +260,26 @@ module Resque
|
|
242
260
|
@paused
|
243
261
|
end
|
244
262
|
|
263
|
+
# Reload
|
245
264
|
def signal_hup
|
246
|
-
|
265
|
+
clean_signal_settings
|
247
266
|
kill_children
|
248
267
|
@paused = false # unpause after kill (restart child)
|
249
268
|
end
|
250
269
|
|
270
|
+
# Stop
|
251
271
|
def signal_usr1
|
252
|
-
log "USR1 received; killing little children..."
|
253
272
|
kill_children
|
254
273
|
@paused = true # pause after kill cause we're paused
|
255
274
|
end
|
256
275
|
|
276
|
+
# Pause
|
257
277
|
def signal_usr2
|
258
|
-
log "USR2 received; not making babies"
|
259
278
|
@paused = true # paused again
|
260
279
|
end
|
261
280
|
|
281
|
+
# Continue
|
262
282
|
def signal_cont
|
263
|
-
log "CONT received; making babies..."
|
264
283
|
@paused = false # unpause
|
265
284
|
end
|
266
285
|
|
@@ -16,14 +16,40 @@ $(document).ready(function() {
|
|
16
16
|
});
|
17
17
|
return new_ary.join(',');
|
18
18
|
};
|
19
|
-
// Click function for all
|
20
|
-
$(".
|
21
|
-
var
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
// Click function for all icons
|
20
|
+
$(".ui-icon").click(function() {
|
21
|
+
var host_sig = $(this).attr("id").split('-');
|
22
|
+
var host = host_sig[0];
|
23
|
+
switch(host_sig[1])
|
24
|
+
{
|
25
|
+
case 'REFRESH':
|
26
|
+
sig = 'reload';
|
27
|
+
break;
|
28
|
+
case 'ALERT':
|
29
|
+
return false;
|
30
|
+
default:
|
31
|
+
sig = host_sig[1].toLowerCase();
|
32
|
+
}
|
33
|
+
var signal = {};
|
34
|
+
signal[sig] = true;
|
35
|
+
|
36
|
+
var span = $(this);
|
37
|
+
$.post('/sliders/' + host, signal, function(data) {
|
38
|
+
switch(data.signal) {
|
39
|
+
case 'reload':
|
40
|
+
span.removeClass('ui-icon-refresh').addClass('ui-icon-alert').attr('id', [host, 'ALERT'].join('-'));
|
41
|
+
break;
|
42
|
+
case 'pause':
|
43
|
+
span.removeClass('ui-icon-pause').addClass('ui-icon-play').attr('id', [host, 'PLAY'].join('-'));
|
44
|
+
break;
|
45
|
+
case 'play':
|
46
|
+
span.removeClass('ui-icon-play').addClass('ui-icon-pause').attr('id', [host, 'PAUSE'].join('-'));
|
47
|
+
break;
|
48
|
+
case 'stop':
|
49
|
+
$('#'+ host + '-PAUSE').removeClass('ui-icon-pause').addClass('ui-icon-play').attr('id', [host, 'PLAY'].join('-'));
|
50
|
+
break;
|
51
|
+
}
|
52
|
+
}, "json");
|
27
53
|
});
|
28
54
|
$('.new_form').submit(function() {
|
29
55
|
var queue = sanitize_input($("#new_queue").val());
|
@@ -12,10 +12,7 @@
|
|
12
12
|
<% max = @sliders.max_children(host) || 'Not running' %>
|
13
13
|
|
14
14
|
<h2><%= "#{host} (Total: <span id=\"total\"></span> Max: <span id=\"max\">#{max}</span>)" %>
|
15
|
-
|
16
|
-
<% if @sliders.reload?(host) %>
|
17
|
-
<span class="ui-icon ui-icon-alert corner"></span>
|
18
|
-
<% end %>
|
15
|
+
<%= daemon_buttons(host, false) %>
|
19
16
|
</h2>
|
20
17
|
<% @sliders.queue_values(host).each_pair do |queue,value| %>
|
21
18
|
<p>
|
@@ -33,7 +30,7 @@
|
|
33
30
|
<tr>
|
34
31
|
<th>Hostname</th>
|
35
32
|
<th>Current / Max Workers</th>
|
36
|
-
<th>
|
33
|
+
<th>Controls</th>
|
37
34
|
</tr>
|
38
35
|
<% @sliders.all_hosts.each do |host| %>
|
39
36
|
<tr>
|
@@ -46,10 +43,7 @@
|
|
46
43
|
</td>
|
47
44
|
<td>
|
48
45
|
<ul>
|
49
|
-
|
50
|
-
<% if @sliders.reload?(host) %>
|
51
|
-
<li class="icons"><span class="ui-icon ui-icon-alert"></span></li>
|
52
|
-
<% end %>
|
46
|
+
<%= daemon_buttons(host) %>
|
53
47
|
</ul>
|
54
48
|
</td>
|
55
49
|
</tr>
|
@@ -28,6 +28,7 @@ module Resque
|
|
28
28
|
end
|
29
29
|
|
30
30
|
app.post '/sliders/:host' do
|
31
|
+
signals = params.reject { |x,y| x unless %w(pause stop play reload).include? x.to_s and y }
|
31
32
|
if params[:quantity] && params[:queue]
|
32
33
|
sliders = Commander.new
|
33
34
|
queue = params[:queue].split.first
|
@@ -37,9 +38,12 @@ module Resque
|
|
37
38
|
else
|
38
39
|
sliders.change(params[:host], queue, quantity)
|
39
40
|
end
|
40
|
-
elsif
|
41
|
+
elsif signals.length == 1
|
41
42
|
sliders = Commander.new
|
42
|
-
|
43
|
+
sig = signals.keys.first.to_s
|
44
|
+
sliders.set_signal_flag(sig, params[:host])
|
45
|
+
content_type :json
|
46
|
+
{:signal => sig, :host => params[:host]}.to_json
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
@@ -57,6 +61,29 @@ module Resque
|
|
57
61
|
404
|
58
62
|
end
|
59
63
|
end
|
64
|
+
|
65
|
+
def daemon_buttons(host, list=true)
|
66
|
+
html_out = []
|
67
|
+
icon_base = 'ui-icon ui-corner-all ui-state-default'
|
68
|
+
case
|
69
|
+
when @sliders.reload?(host)
|
70
|
+
%w(pause stop alert)
|
71
|
+
when (@sliders.pause?(host) or @sliders.stop?(host))
|
72
|
+
%w(play stop refresh)
|
73
|
+
else
|
74
|
+
%w(pause stop refresh)
|
75
|
+
end.each do |i|
|
76
|
+
id = "#{host}-#{i.upcase}"
|
77
|
+
klass = "#{icon_base} ui-icon-#{i}"
|
78
|
+
klass += ' corner' unless list
|
79
|
+
html_out << "<span id=\"#{id}\" class=\"#{klass}\"></span>"
|
80
|
+
end
|
81
|
+
if list
|
82
|
+
'<li class="icons">' + html_out.join("</li><li class=\"icons\">") + '</li>'
|
83
|
+
else
|
84
|
+
html_out.reverse.join
|
85
|
+
end
|
86
|
+
end
|
60
87
|
end
|
61
88
|
|
62
89
|
app.tabs << "Sliders"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-sliders
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kevin Mullin
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
18
|
+
date: 2012-01-10 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|