Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ GEM
xpath (~> 0.1.4)
childprocess (0.3.9)
ffi (~> 1.0, >= 1.0.11)
coderay (1.1.0)
columnize (0.3.6)
daemons (1.1.9)
debugger (1.6.2)
Expand All @@ -40,6 +41,7 @@ GEM
http_parser.rb (0.5.3)
launchy (2.1.2)
addressable (~> 2.3)
method_source (0.8.2)
metriks (0.9.9.5)
atomic (~> 1.0)
avl_tree (~> 1.1.2)
Expand All @@ -60,6 +62,10 @@ GEM
http_parser.rb (~> 0.5.3)
multi_json (~> 1.0)
powerpack (0.0.8)
pry (0.9.12.6)
coderay (~> 1.0)
method_source (~> 0.8)
slop (~> 3.4)
rack (1.5.2)
rack-protection (1.5.0)
rack
Expand Down Expand Up @@ -125,6 +131,7 @@ DEPENDENCIES
launchy (~> 2.1.0)
metriks (~> 0.9)
poltergeist (~> 1.0.0)
pry
qless!
rake (~> 10.0)
rspec (~> 2.12)
Expand Down
6 changes: 6 additions & 0 deletions lib/qless.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ def initialize(client)
def [](name)
Throttle.new(name, @client)
end

def counts
@client.queues.counts.map do |queue|
Throttle.new(queue['name'], @client)
end
end
end

# A class for interacting with events. Not meant to be instantiated directly,
Expand Down
45 changes: 45 additions & 0 deletions lib/qless/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def paginated(qless_object, method, *args)
def tabs
[
{ name: 'Queues' , path: '/queues' },
{ name: 'Throttles', path: '/throttles'},
{ name: 'Workers' , path: '/workers' },
{ name: 'Track' , path: '/track' },
{ name: 'Failed' , path: '/failed' },
Expand All @@ -95,6 +96,10 @@ def queues
client.queues.counts
end

def throttles
client.throttles.counts
end

def tracked
client.jobs.tracked
end
Expand Down Expand Up @@ -194,6 +199,46 @@ def strftime(t)
}
end

get '/throttles/?' do
erb :throttles, layout: true, locals: {
title: 'Throttles'
}
end

post '/throttle' do
# Expects a JSON object: {'id': id, 'maximum': maximum}
data = JSON.parse(request.body.read)
if data['id'].nil? || data['maximum'].nil?
halt 400, 'Need throttle id and maximum value'
else
throttle = Throttle.new(data['id'], client)
throttle.maximum = data['maximum']
end
end

put '/throttle' do
# Expects a JSON object: {'id': id, 'expiration': expiration}
data = JSON.parse(request.body.read)
if data['id'].nil? || data['expiration'].nil?
halt 400, 'Need throttle id and expiration value'
else
throttle = Throttle.new(data['id'], client)
throttle.expiration = data['expiration']
end
end

delete '/throttle' do
# Expects a JSON object: {'id': id}
data = JSON.parse(request.body.read)
if data['id'].nil?
halt 400, 'Need throttle id'
else
throttle = Throttle.new(data['id'], client)
throttle.delete
return json({id: throttle.id, maximum: throttle.maximum})
end
end

get '/failed.json' do
json(client.jobs.failed)
end
Expand Down
51 changes: 51 additions & 0 deletions lib/qless/server/views/layout.erb
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,57 @@
})
}

var expire_throttle = function(throttle_id, expiration) {
var data = { 'id': throttle_id, 'expiration': expiration };

$.ajax({
url: '<%= u "/throttle" %>',
type: 'PUT',
dataType: 'json',
processData: false,
data: JSON.stringify(data),
success: function(data) {
flash('Set expiration for throttle ' + throttle_id, 'success');
},
error: function(data) {
flash('Couldn\'t update expiration for throttle ' + throttle_id);
}
})
}

var delete_throttle = function(throttle_id) {
var data = { 'id': throttle_id };

$.ajax({
url: '<%= u "/throttle" %>',
type: 'DELETE',
dataType: 'json',
processData: false,
data: JSON.stringify(data),
success: function(data) {
flash('Deleted throttle for ' + throttle_id, 'success');
$('.' + throttle_id + '-maximum').val(data['maximum']);
},
error: function(data) {
flash('Couldn\'t delete thottle ' + throttle_id);
}
})
}

var update_throttle = function(throttle_id, maximum) {
_ajax({
url: '<%= u "/throttle" %>',
data: {
'id': throttle_id,
'maximum': maximum
}, success: function(data) {
flash('Updated throttle for ' + throttle_id, 'success');
}, error: function(data) {
flash('Couldn\'t update throttle ' + throttle_id);
}
})
}

$(document).ready(function() {
$('button').tooltip({delay:200});
});
Expand Down
38 changes: 38 additions & 0 deletions lib/qless/server/views/throttles.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<% if throttles.empty? %>
<div class="page-header">
<h1>No Queues To Throttle <small>What a fine predicament to be in...</small></h1>
</div>
<% else %>
<div class="page-header">
<h1>Throttles <small>By queue.</small></h1>
</div>

<table class="table">
<thead>
<tr>
<th> Queue </th>
<th> Maximum </th>
<th> TTL (sets expiration) </th>
<th> Reset </th>
</tr>
</thead>
<tbody>
<% throttles.each do |throttle| %>
<tr class="tracked-row">
<td class="large-text"><%= throttle.id %></td>
<td>
<input class="span1 <%= throttle.id %>-maximum" type="text" placeholder="<%= throttle.maximum %>" onchange="update_throttle('<%= throttle.id %>', $(this).val())"></input>
</td>
<td>
<input class="span1 <%= throttle.id %>-expiration" type="text" placeholder="<%= throttle.ttl %>" onchange="expire_throttle('<%= throttle.id %>', $(this).val())"></input>
</td>
<td>
<button title="delete" class="btn btn-danger" onclick="confirmation(this, 'Delete?', function() { delete_throttle('<%= throttle.id %>', fade) })">
<i class="icon-remove"></i>
</button>
</td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
1 change: 0 additions & 1 deletion lib/qless/throttle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,5 @@ def throttle_attrs
def update(max, expiration = 0)
@client.call('throttle.set', @name, max || maximum, expiration)
end

end
end
1 change: 1 addition & 0 deletions qless.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ language-specific extension will also remain up to date.
s.add_development_dependency 'rubocop' , '~> 0.13.1'
s.add_development_dependency 'rusage' , '~> 0.2.0'
s.add_development_dependency 'timecop' , '~> 0.7.1'
s.add_development_dependency 'pry'
end
59 changes: 59 additions & 0 deletions spec/integration/server_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require 'capybara/rspec'
require 'capybara/poltergeist'
require 'rack/test'
require 'pry'

Capybara.javascript_driver = :poltergeist

Expand Down Expand Up @@ -122,6 +123,64 @@ def test_pagination(page_1_jid = 1, page_2_jid = 27)
test_pagination
end

it 'can set and delete throttles for all the queues', js: true do
q.put(Qless::Job, {})

text_field_class = ".#{q.name}-maximum"
throttle = Throttle.new(q.name, client)

throttle.maximum.should eq(0)

visit '/throttles'

first('td', text: /#{q.name}/i).should be
first(text_field_class, placeholder: /0/i).should be

maximum = first(text_field_class)
maximum.set(3)
maximum.trigger('blur');

first(text_field_class, value: /3/i).should be
throttle.maximum.should eq(3)

first('button.btn-danger').click
first('button.btn-danger').click

first(text_field_class, value: /0/i).should be
end

it 'can set the expiration for throttles', js: true do
q.put(Qless::Job, {})

maximum_field_class = ".#{q.name}-maximum"
expiration_field_class = ".#{q.name}-expiration"
throttle = Throttle.new(q.name, client)

throttle.maximum.should eq(0)
throttle.ttl.should eq(-2)

visit '/throttles'

first('td', text: /#{q.name}/i).should be
first(expiration_field_class, placeholder: /-2/i).should be

maximum = first(maximum_field_class)
maximum.set(3)
maximum.trigger('blur');

first(maximum_field_class, value: /3/i).should be
throttle.maximum.should eq(3)

expiration = first(expiration_field_class)
expiration.set(1)
expiration.trigger('blur');

visit '/throttles'

first(maximum_field_class, value: /0/i).should be
first(expiration_field_class, placeholder: /-2/i).should be
end

it 'can see the root-level summary' do
visit '/'

Expand Down