sidekiq 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- data/Changes.md +11 -0
- data/Gemfile +7 -1
- data/LICENSE +7 -1
- data/README.md +2 -0
- data/TODO.md +1 -2
- data/bin/sidekiq +1 -1
- data/config.ru +8 -0
- data/examples/config.yml +0 -2
- data/examples/scheduling.rb +37 -0
- data/lib/sidekiq.rb +25 -11
- data/lib/sidekiq/capistrano.rb +8 -5
- data/lib/sidekiq/cli.rb +20 -21
- data/lib/sidekiq/client.rb +9 -6
- data/lib/sidekiq/extensions/action_mailer.rb +1 -2
- data/lib/sidekiq/extensions/active_record.rb +1 -3
- data/lib/sidekiq/extensions/generic_proxy.rb +1 -1
- data/lib/sidekiq/manager.rb +28 -22
- data/lib/sidekiq/middleware/client/unique_jobs.rb +3 -3
- data/lib/sidekiq/middleware/server/failure_jobs.rb +1 -1
- data/lib/sidekiq/middleware/server/unique_jobs.rb +1 -1
- data/lib/sidekiq/processor.rb +4 -6
- data/lib/sidekiq/rails.rb +16 -1
- data/lib/sidekiq/redis_connection.rb +3 -3
- data/lib/sidekiq/util.rb +3 -15
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +93 -0
- data/lib/sidekiq/worker.rb +0 -4
- data/myapp/Gemfile +15 -3
- data/myapp/app/controllers/work_controller.rb +1 -1
- data/myapp/config/initializers/sidekiq.rb +2 -2
- data/myapp/config/routes.rb +2 -2
- data/sidekiq.gemspec +3 -1
- data/test/helper.rb +4 -0
- data/test/test_cli.rb +26 -14
- data/test/test_client.rb +2 -2
- data/test/test_extensions.rb +11 -7
- data/test/test_manager.rb +2 -3
- data/test/test_middleware.rb +1 -1
- data/test/test_stats.rb +28 -29
- data/test/test_testing.rb +47 -14
- data/test/test_web.rb +51 -0
- data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
- data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
- data/web/assets/javascripts/application.js +3 -0
- data/web/assets/javascripts/vendor/bootstrap.js +12 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-alert.js +91 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-button.js +98 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-carousel.js +154 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-collapse.js +136 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-dropdown.js +92 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-modal.js +210 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-popover.js +95 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-scrollspy.js +125 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tab.js +130 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tooltip.js +270 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-transition.js +51 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-typeahead.js +271 -0
- data/web/assets/javascripts/vendor/jquery.js +9266 -0
- data/web/assets/stylesheets/application.css +11 -0
- data/web/assets/stylesheets/vendor/bootstrap-responsive.css +567 -0
- data/web/assets/stylesheets/vendor/bootstrap.css +3365 -0
- data/web/views/index.slim +42 -0
- data/web/views/layout.slim +24 -0
- data/web/views/queue.slim +11 -0
- metadata +71 -22
- data/lib/sidekiq/middleware/client/resque_web_compatibility.rb +0 -14
data/test/test_manager.rb
CHANGED
@@ -8,9 +8,8 @@ require 'connection_pool'
|
|
8
8
|
class TestManager < MiniTest::Unit::TestCase
|
9
9
|
describe 'with redis' do
|
10
10
|
before do
|
11
|
-
Sidekiq.redis =
|
12
|
-
|
13
|
-
@redis.flushdb
|
11
|
+
Sidekiq.redis = REDIS
|
12
|
+
Sidekiq.redis.flushdb
|
14
13
|
$processed = 0
|
15
14
|
$mutex = Mutex.new
|
16
15
|
end
|
data/test/test_middleware.rb
CHANGED
data/test/test_stats.rb
CHANGED
@@ -5,48 +5,50 @@ require 'sidekiq/processor'
|
|
5
5
|
class TestStats < MiniTest::Unit::TestCase
|
6
6
|
describe 'with redis' do
|
7
7
|
before do
|
8
|
-
Sidekiq.redis =
|
9
|
-
|
10
|
-
@redis.flushdb
|
8
|
+
@redis = Sidekiq.redis = REDIS
|
9
|
+
Sidekiq.redis.flushdb
|
11
10
|
end
|
12
11
|
|
13
12
|
class DumbWorker
|
14
13
|
include Sidekiq::Worker
|
15
14
|
|
16
|
-
def perform(
|
17
|
-
raise 'bang' if
|
15
|
+
def perform(arg)
|
16
|
+
raise 'bang' if arg == nil
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
20
|
it 'updates global stats in the success case' do
|
22
|
-
msg = { 'class' => DumbWorker.to_s, 'args' => [
|
21
|
+
msg = { 'class' => DumbWorker.to_s, 'args' => [""] }
|
23
22
|
boss = MiniTest::Mock.new
|
24
23
|
|
25
|
-
|
26
|
-
assert_equal 0, set.size
|
24
|
+
@redis.with do |conn|
|
27
25
|
|
28
|
-
|
29
|
-
|
26
|
+
set = conn.smembers('workers')
|
27
|
+
assert_equal 0, set.size
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
assert_equal 1, set.size
|
34
|
-
assert_match(/#{Regexp.escape(`hostname`.strip)}/, set.first)
|
29
|
+
processor = Sidekiq::Processor.new(boss)
|
30
|
+
boss.expect(:processor_done!, nil, [processor])
|
35
31
|
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
# adds to the workers set upon initialize
|
33
|
+
set = conn.smembers('workers')
|
34
|
+
assert_equal 1, set.size
|
35
|
+
assert_match(/#{Regexp.escape(`hostname`.strip)}/, set.first)
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
assert_equal 0, conn.get('stat:failed').to_i
|
38
|
+
assert_equal 0, conn.get('stat:processed').to_i
|
39
|
+
assert_equal 0, conn.get("stat:processed:#{processor}").to_i
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
processor.process(msg, 'xyzzy')
|
42
|
+
processor.process(msg, 'xyzzy')
|
43
|
+
processor.process(msg, 'xyzzy')
|
44
|
+
|
45
|
+
set = conn.smembers('workers')
|
46
|
+
assert_equal 1, set.size
|
47
|
+
assert_match(/#{Regexp.escape(`hostname`.strip)}/, set.first)
|
48
|
+
assert_equal 0, conn.get('stat:failed').to_i
|
49
|
+
assert_equal 3, conn.get('stat:processed').to_i
|
50
|
+
assert_equal 3, conn.get("stat:processed:#{processor}").to_i
|
51
|
+
end
|
50
52
|
end
|
51
53
|
|
52
54
|
it 'updates global stats in the error case' do
|
@@ -72,8 +74,5 @@ class TestStats < MiniTest::Unit::TestCase
|
|
72
74
|
assert_equal nil, @redis.get("stat:processed:#{pstr}")
|
73
75
|
end
|
74
76
|
|
75
|
-
it 'should set various stats during processing' do
|
76
|
-
skip 'TODO'
|
77
|
-
end
|
78
77
|
end
|
79
78
|
end
|
data/test/test_testing.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'sidekiq'
|
2
3
|
require 'sidekiq/worker'
|
4
|
+
require 'active_record'
|
5
|
+
require 'action_mailer'
|
6
|
+
require 'sidekiq/extensions/action_mailer'
|
7
|
+
require 'sidekiq/extensions/active_record'
|
8
|
+
|
9
|
+
Sidekiq.hook_rails!
|
3
10
|
|
4
11
|
class TestTesting < MiniTest::Unit::TestCase
|
5
12
|
describe 'sidekiq testing' do
|
@@ -11,22 +18,48 @@ class TestTesting < MiniTest::Unit::TestCase
|
|
11
18
|
end
|
12
19
|
end
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
Sidekiq::Worker::ClassMethods.class_eval do
|
24
|
-
remove_method :perform_async
|
25
|
-
alias_method :perform_async, :perform_async_old
|
26
|
-
remove_method :perform_async_old
|
27
|
-
end
|
21
|
+
class FooMailer < ActionMailer::Base
|
22
|
+
def bar(str)
|
23
|
+
str
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class FooModel < ActiveRecord::Base
|
28
|
+
def bar(str)
|
29
|
+
str
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
33
|
+
before do
|
34
|
+
require 'sidekiq/testing'
|
35
|
+
end
|
36
|
+
|
37
|
+
after do
|
38
|
+
# Undo override
|
39
|
+
Sidekiq::Worker::ClassMethods.class_eval do
|
40
|
+
remove_method :perform_async
|
41
|
+
alias_method :perform_async, :perform_async_old
|
42
|
+
remove_method :perform_async_old
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'stubs the async call when in testing mode' do
|
47
|
+
# We can only have one it block here so all 'testing' tests
|
48
|
+
# have to go here because require 'sidekiq/testing' changes
|
49
|
+
# how Sidekiq works and we need to roll back those changes
|
50
|
+
# when the test is done.
|
51
|
+
assert_equal 0, DirectWorker.jobs.size
|
52
|
+
assert DirectWorker.perform_async(1, 2)
|
53
|
+
assert_equal 1, DirectWorker.jobs.size
|
54
|
+
|
55
|
+
assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
|
56
|
+
FooMailer.delay.bar('hello!')
|
57
|
+
assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
|
58
|
+
|
59
|
+
assert_equal 0, Sidekiq::Extensions::DelayedModel.jobs.size
|
60
|
+
FooModel.delay.bar('hello!')
|
61
|
+
assert_equal 1, Sidekiq::Extensions::DelayedModel.jobs.size
|
62
|
+
end
|
63
|
+
|
31
64
|
end
|
32
65
|
end
|
data/test/test_web.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'sidekiq'
|
3
|
+
require 'sidekiq/web'
|
4
|
+
require 'rack/test'
|
5
|
+
|
6
|
+
class TestWeb < MiniTest::Unit::TestCase
|
7
|
+
describe 'sidekiq web' do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
def app
|
11
|
+
Sidekiq::Web
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
Sidekiq.redis = REDIS
|
16
|
+
Sidekiq.redis.flushdb
|
17
|
+
end
|
18
|
+
|
19
|
+
class WebWorker
|
20
|
+
include Sidekiq::Worker
|
21
|
+
|
22
|
+
def perform(a, b)
|
23
|
+
a + b
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'shows active queues' do
|
28
|
+
get '/'
|
29
|
+
assert_equal 200, last_response.status
|
30
|
+
assert_match last_response.body, /Sidekiq is down/
|
31
|
+
refute_match last_response.body, /default/
|
32
|
+
|
33
|
+
assert WebWorker.perform_async(1, 2)
|
34
|
+
|
35
|
+
get '/'
|
36
|
+
assert_equal 200, last_response.status
|
37
|
+
assert_match last_response.body, /Sidekiq is down/
|
38
|
+
assert_match last_response.body, /default/
|
39
|
+
refute_match last_response.body, /foo/
|
40
|
+
|
41
|
+
assert Sidekiq::Client.push(:foo, 'class' => WebWorker, 'args' => [1, 3])
|
42
|
+
|
43
|
+
get '/'
|
44
|
+
assert_equal 200, last_response.status
|
45
|
+
assert_match last_response.body, /Sidekiq is down/
|
46
|
+
assert_match last_response.body, /default/
|
47
|
+
assert_match last_response.body, /foo/
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
//= require vendor/bootstrap/bootstrap-transition
|
2
|
+
//= require vendor/bootstrap/bootstrap-alert
|
3
|
+
//= require vendor/bootstrap/bootstrap-modal
|
4
|
+
//= require vendor/bootstrap/bootstrap-dropdown
|
5
|
+
//= require vendor/bootstrap/bootstrap-scrollspy
|
6
|
+
//= require vendor/bootstrap/bootstrap-tab
|
7
|
+
//= require vendor/bootstrap/bootstrap-tooltip
|
8
|
+
//= require vendor/bootstrap/bootstrap-popover
|
9
|
+
//= require vendor/bootstrap/bootstrap-button
|
10
|
+
//= require vendor/bootstrap/bootstrap-collapse
|
11
|
+
//= require vendor/bootstrap/bootstrap-carousel
|
12
|
+
//= require vendor/bootstrap/bootstrap-typeahead
|
@@ -0,0 +1,91 @@
|
|
1
|
+
/* ==========================================================
|
2
|
+
* bootstrap-alert.js v2.0.0
|
3
|
+
* http://twitter.github.com/bootstrap/javascript.html#alerts
|
4
|
+
* ==========================================================
|
5
|
+
* Copyright 2012 Twitter, Inc.
|
6
|
+
*
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
* you may not use this file except in compliance with the License.
|
9
|
+
* You may obtain a copy of the License at
|
10
|
+
*
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
*
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
* See the License for the specific language governing permissions and
|
17
|
+
* limitations under the License.
|
18
|
+
* ========================================================== */
|
19
|
+
|
20
|
+
|
21
|
+
!function( $ ){
|
22
|
+
|
23
|
+
"use strict"
|
24
|
+
|
25
|
+
/* ALERT CLASS DEFINITION
|
26
|
+
* ====================== */
|
27
|
+
|
28
|
+
var dismiss = '[data-dismiss="alert"]'
|
29
|
+
, Alert = function ( el ) {
|
30
|
+
$(el).on('click', dismiss, this.close)
|
31
|
+
}
|
32
|
+
|
33
|
+
Alert.prototype = {
|
34
|
+
|
35
|
+
constructor: Alert
|
36
|
+
|
37
|
+
, close: function ( e ) {
|
38
|
+
var $this = $(this)
|
39
|
+
, selector = $this.attr('data-target')
|
40
|
+
, $parent
|
41
|
+
|
42
|
+
if (!selector) {
|
43
|
+
selector = $this.attr('href')
|
44
|
+
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
45
|
+
}
|
46
|
+
|
47
|
+
$parent = $(selector)
|
48
|
+
$parent.trigger('close')
|
49
|
+
|
50
|
+
e && e.preventDefault()
|
51
|
+
|
52
|
+
$parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
|
53
|
+
|
54
|
+
$parent.removeClass('in')
|
55
|
+
|
56
|
+
function removeElement() {
|
57
|
+
$parent.remove()
|
58
|
+
$parent.trigger('closed')
|
59
|
+
}
|
60
|
+
|
61
|
+
$.support.transition && $parent.hasClass('fade') ?
|
62
|
+
$parent.on($.support.transition.end, removeElement) :
|
63
|
+
removeElement()
|
64
|
+
}
|
65
|
+
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
/* ALERT PLUGIN DEFINITION
|
70
|
+
* ======================= */
|
71
|
+
|
72
|
+
$.fn.alert = function ( option ) {
|
73
|
+
return this.each(function () {
|
74
|
+
var $this = $(this)
|
75
|
+
, data = $this.data('alert')
|
76
|
+
if (!data) $this.data('alert', (data = new Alert(this)))
|
77
|
+
if (typeof option == 'string') data[option].call($this)
|
78
|
+
})
|
79
|
+
}
|
80
|
+
|
81
|
+
$.fn.alert.Constructor = Alert
|
82
|
+
|
83
|
+
|
84
|
+
/* ALERT DATA-API
|
85
|
+
* ============== */
|
86
|
+
|
87
|
+
$(function () {
|
88
|
+
$('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
|
89
|
+
})
|
90
|
+
|
91
|
+
}( window.jQuery )
|
@@ -0,0 +1,98 @@
|
|
1
|
+
/* ============================================================
|
2
|
+
* bootstrap-button.js v2.0.0
|
3
|
+
* http://twitter.github.com/bootstrap/javascript.html#buttons
|
4
|
+
* ============================================================
|
5
|
+
* Copyright 2012 Twitter, Inc.
|
6
|
+
*
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
* you may not use this file except in compliance with the License.
|
9
|
+
* You may obtain a copy of the License at
|
10
|
+
*
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
*
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
* See the License for the specific language governing permissions and
|
17
|
+
* limitations under the License.
|
18
|
+
* ============================================================ */
|
19
|
+
|
20
|
+
!function( $ ){
|
21
|
+
|
22
|
+
"use strict"
|
23
|
+
|
24
|
+
/* BUTTON PUBLIC CLASS DEFINITION
|
25
|
+
* ============================== */
|
26
|
+
|
27
|
+
var Button = function ( element, options ) {
|
28
|
+
this.$element = $(element)
|
29
|
+
this.options = $.extend({}, $.fn.button.defaults, options)
|
30
|
+
}
|
31
|
+
|
32
|
+
Button.prototype = {
|
33
|
+
|
34
|
+
constructor: Button
|
35
|
+
|
36
|
+
, setState: function ( state ) {
|
37
|
+
var d = 'disabled'
|
38
|
+
, $el = this.$element
|
39
|
+
, data = $el.data()
|
40
|
+
, val = $el.is('input') ? 'val' : 'html'
|
41
|
+
|
42
|
+
state = state + 'Text'
|
43
|
+
data.resetText || $el.data('resetText', $el[val]())
|
44
|
+
|
45
|
+
$el[val](data[state] || this.options[state])
|
46
|
+
|
47
|
+
// push to event loop to allow forms to submit
|
48
|
+
setTimeout(function () {
|
49
|
+
state == 'loadingText' ?
|
50
|
+
$el.addClass(d).attr(d, d) :
|
51
|
+
$el.removeClass(d).removeAttr(d)
|
52
|
+
}, 0)
|
53
|
+
}
|
54
|
+
|
55
|
+
, toggle: function () {
|
56
|
+
var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
|
57
|
+
|
58
|
+
$parent && $parent
|
59
|
+
.find('.active')
|
60
|
+
.removeClass('active')
|
61
|
+
|
62
|
+
this.$element.toggleClass('active')
|
63
|
+
}
|
64
|
+
|
65
|
+
}
|
66
|
+
|
67
|
+
|
68
|
+
/* BUTTON PLUGIN DEFINITION
|
69
|
+
* ======================== */
|
70
|
+
|
71
|
+
$.fn.button = function ( option ) {
|
72
|
+
return this.each(function () {
|
73
|
+
var $this = $(this)
|
74
|
+
, data = $this.data('button')
|
75
|
+
, options = typeof option == 'object' && option
|
76
|
+
if (!data) $this.data('button', (data = new Button(this, options)))
|
77
|
+
if (option == 'toggle') data.toggle()
|
78
|
+
else if (option) data.setState(option)
|
79
|
+
})
|
80
|
+
}
|
81
|
+
|
82
|
+
$.fn.button.defaults = {
|
83
|
+
loadingText: 'loading...'
|
84
|
+
}
|
85
|
+
|
86
|
+
$.fn.button.Constructor = Button
|
87
|
+
|
88
|
+
|
89
|
+
/* BUTTON DATA-API
|
90
|
+
* =============== */
|
91
|
+
|
92
|
+
$(function () {
|
93
|
+
$('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
|
94
|
+
$(e.target).button('toggle')
|
95
|
+
})
|
96
|
+
})
|
97
|
+
|
98
|
+
}( window.jQuery )
|