sidekiq 2.11.2 → 2.12.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 CHANGED
@@ -1,3 +1,18 @@
1
+ 2.12.0
2
+ -----------
3
+
4
+ - Upgrade to Celluloid 0.14, remove the use of Celluloid's thread
5
+ pool. This should halve the number of threads in each Sidekiq
6
+ process, thus requiring less resources. [#919]
7
+ - Abstract Celluloid usage to Sidekiq::Actor for testing purposes.
8
+ - Better handling for Redis downtime when fetching jobs and shutting
9
+ down, don't print exceptions every second and print success message
10
+ when Redis is back.
11
+ - Fix unclean shutdown leading to duplicate jobs [#897]
12
+ - Add Korean locale [#890]
13
+ - Upgrade test suite to Minitest 5
14
+ - Remove usage of `multi_json` as `json` is now robust on all platforms.
15
+
1
16
  2.11.2
2
17
  -----------
3
18
 
data/Gemfile CHANGED
@@ -1,7 +1,6 @@
1
1
  source 'http://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem 'celluloid', "~> 0.13.0"
5
4
  gem 'slim'
6
5
  gem 'sqlite3', :platform => :mri
7
6
 
@@ -0,0 +1,127 @@
1
+ Sidekiq Pro Changelog
2
+ =======================
3
+
4
+ Please see http://sidekiq.org/pro for more details and how to buy.
5
+
6
+ HEAD
7
+ -----------
8
+
9
+ - New `sidekiq/pro/reliable_push` which makes Sidekiq::Client resiliant
10
+ to Redis network failures. [#793]
11
+ - Move `sidekiq/reliable_fetch` to `sidekiq/pro/reliable_fetch`
12
+
13
+
14
+ 1.0.0
15
+ -----------
16
+
17
+ - Sidekiq Pro changelog moved to mperham/sidekiq for public visibility.
18
+ - Add new Rack endpoint for easy polling of batch status via JavaScript. See `sidekiq/rack/batch_status`
19
+
20
+ 0.9.3
21
+ -----------
22
+
23
+ - Fix bad /batches path in Web UI
24
+ - Fix Sinatra conflict with sidekiq-failures
25
+
26
+ 0.9.2
27
+ -----------
28
+
29
+ - Fix issue with lifecycle notifications not firing.
30
+
31
+ 0.9.1
32
+ -----------
33
+
34
+ - Update due to Sidekiq API changes.
35
+
36
+ 0.9.0
37
+ -----------
38
+
39
+ - Rearchitect Sidekiq's Fetch code to support different fetch
40
+ strategies. Add a ReliableFetch strategy which works with Redis'
41
+ RPOPLPUSH to ensure we don't lose messages, even when the Sidekiq
42
+ process crashes unexpectedly. [mperham/sidekiq#607]
43
+
44
+ 0.8.2
45
+ -----------
46
+
47
+ - Reimplement existing notifications using batch on_complete events.
48
+
49
+ 0.8.1
50
+ -----------
51
+
52
+ - Rejigger batch callback notifications.
53
+
54
+
55
+ 0.8.0
56
+ -----------
57
+
58
+ - Add new Batch 'callback' notification support, for in-process
59
+ notification.
60
+ - Symbolize option keys passed to Pony [mperham/sidekiq#603]
61
+ - Batch no longer requires the Web UI since Web UI usage is optional.
62
+ You must require is manually in your Web process:
63
+
64
+ ```ruby
65
+ require 'sidekiq/web'
66
+ require 'sidekiq/batch/web'
67
+ mount Sidekiq::Web => '/sidekiq'
68
+ ```
69
+
70
+
71
+ 0.7.1
72
+ -----------
73
+
74
+ - Worker instances can access the associated jid and bid via simple
75
+ accessors.
76
+ - Batches can now be modified while being processed so, e.g. a batch
77
+ job can add additional jobs to its own batch.
78
+
79
+ ```ruby
80
+ def perform(...)
81
+ batch = Sidekiq::Batch.new(bid) # instantiate batch associated with this job
82
+ batch.jobs do
83
+ SomeWorker.perform_async # add another job
84
+ end
85
+ end
86
+ ```
87
+
88
+ - Save error backtraces in batch's failure info for display in Web UI.
89
+ - Clean up email notification a bit.
90
+
91
+
92
+ 0.7.0
93
+ -----------
94
+
95
+ - Add optional batch description
96
+ - Mutable batches. Batches can now be modified to add additional jobs
97
+ at runtime. Example would be a batch job which needs to create more
98
+ jobs based on the data it is processing.
99
+
100
+ ```ruby
101
+ batch = Sidekiq::Batch.new(bid)
102
+ batch.jobs do
103
+ # define more jobs here
104
+ end
105
+ ```
106
+ - Fix issues with symbols vs strings in option hashes
107
+
108
+
109
+ 0.6.1
110
+ -----------
111
+
112
+ - Webhook notification support
113
+
114
+
115
+ 0.6
116
+ -----------
117
+
118
+ - Redis pubsub
119
+ - Email polish
120
+
121
+
122
+ 0.5
123
+ -----------
124
+
125
+ - Batches
126
+ - Notifications
127
+ - Statsd middleware
@@ -7,7 +7,7 @@ require 'sidekiq/redis_connection'
7
7
  require 'sidekiq/util'
8
8
  require 'sidekiq/api'
9
9
 
10
- require 'multi_json'
10
+ require 'json'
11
11
 
12
12
  module Sidekiq
13
13
  NAME = "Sidekiq"
@@ -90,11 +90,11 @@ module Sidekiq
90
90
  end
91
91
 
92
92
  def self.load_json(string)
93
- MultiJson.decode(string, :symbolize_keys => false)
93
+ JSON.parse(string)
94
94
  end
95
95
 
96
96
  def self.dump_json(object)
97
- MultiJson.encode(object)
97
+ JSON.generate(object)
98
98
  end
99
99
 
100
100
  def self.logger
@@ -115,4 +115,3 @@ require 'sidekiq/extensions/class_methods'
115
115
  require 'sidekiq/extensions/action_mailer'
116
116
  require 'sidekiq/extensions/active_record'
117
117
  require 'sidekiq/rails' if defined?(::Rails::Engine)
118
-
@@ -0,0 +1,67 @@
1
+ module Sidekiq
2
+ #
3
+ # Celluloid has the nasty side effect of making objects
4
+ # very hard to test because they are immediately async
5
+ # upon creation. In testing we want to just treat
6
+ # the actors as POROs.
7
+ #
8
+ # Instead of including Celluloid, we'll just stub
9
+ # out the key methods we use so that everything works
10
+ # synchronously. The alternative is no test coverage.
11
+ #
12
+ module Actor
13
+ if $TESTING
14
+
15
+ TaskThread = 0
16
+
17
+ def sleep(amount=0)
18
+ end
19
+
20
+ def after(amount=0)
21
+ end
22
+
23
+ def defer
24
+ yield
25
+ end
26
+
27
+ def current_actor
28
+ self
29
+ end
30
+
31
+ def alive?
32
+ !@dead
33
+ end
34
+
35
+ def terminate
36
+ @dead = true
37
+ end
38
+
39
+ def async
40
+ self
41
+ end
42
+
43
+ def signal(sym)
44
+ end
45
+
46
+ # we don't want to hide or catch failures in testing
47
+ def watchdog(msg)
48
+ yield
49
+ end
50
+
51
+ def self.included(klass)
52
+ class << klass
53
+ alias_method :new_link, :new
54
+ def trap_exit(meth)
55
+ end
56
+ def task_class(konstant)
57
+ end
58
+ end
59
+ end
60
+
61
+ else
62
+ def self.included(klass)
63
+ klass.send(:include, Celluloid)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -33,7 +33,7 @@ module Sidekiq
33
33
  end
34
34
 
35
35
  def send_to_exception_notifier(msg, ex)
36
- ::ExceptionNotifier::Notifier.background_exception_notification(ex, :data => { :message => msg }).deliver
36
+ ::ExceptionNotifier.notify_exception(ex, :data => {:message => msg})
37
37
  end
38
38
  end
39
39
  end
@@ -1,3 +1,5 @@
1
+ require 'yaml'
2
+
1
3
  module Sidekiq
2
4
  module Extensions
3
5
  class Proxy < BasicObject
@@ -1,5 +1,5 @@
1
1
  require 'sidekiq'
2
- require 'celluloid'
2
+ require 'sidekiq/actor'
3
3
 
4
4
  module Sidekiq
5
5
  ##
@@ -7,12 +7,13 @@ module Sidekiq
7
7
  # from the queues. It gets the message and hands it to the Manager
8
8
  # to assign to a ready Processor.
9
9
  class Fetcher
10
- include Celluloid
11
- include Sidekiq::Util
10
+ include Util
11
+ include Actor
12
12
 
13
13
  TIMEOUT = 1
14
14
 
15
15
  def initialize(mgr, options)
16
+ @down = nil
16
17
  @mgr = mgr
17
18
  @strategy = Fetcher.strategy.new(options)
18
19
  end
@@ -31,6 +32,8 @@ module Sidekiq
31
32
 
32
33
  begin
33
34
  work = @strategy.retrieve_work
35
+ ::Sidekiq.logger.info("Redis is online, #{Time.now.to_f - @down.to_f} sec downtime") if @down
36
+ @down = nil
34
37
 
35
38
  if work
36
39
  @mgr.async.assign(work)
@@ -38,12 +41,25 @@ module Sidekiq
38
41
  after(0) { fetch }
39
42
  end
40
43
  rescue => ex
41
- logger.error("Error fetching message: #{ex}")
42
- logger.error(ex.backtrace.first)
43
- sleep(TIMEOUT)
44
- after(0) { fetch }
44
+ handle_exception(ex)
45
+ end
46
+
47
+ end
48
+ end
49
+
50
+ def handle_exception(ex)
51
+ if !@down
52
+ logger.error("Error fetching message: #{ex}")
53
+ ex.backtrace.each do |bt|
54
+ logger.error(bt)
45
55
  end
46
56
  end
57
+ @down ||= Time.now
58
+ sleep(TIMEOUT)
59
+ after(0) { fetch }
60
+ rescue Task::TerminatedError
61
+ # If redis is down when we try to shut down, all the fetch backlog
62
+ # raises these errors. Haven't been able to figure out what I'm doing wrong.
47
63
  end
48
64
 
49
65
  # Ugh. Say hello to a bloody hack.
@@ -88,6 +104,8 @@ module Sidekiq
88
104
  end
89
105
  end
90
106
  Sidekiq.logger.info("Pushed #{inprogress.size} messages back to Redis")
107
+ rescue => ex
108
+ Sidekiq.logger.warn("Failed to requeue #{inprogress.size} jobs: #{ex.message}")
91
109
  end
92
110
 
93
111
  UnitOfWork = Struct.new(:queue, :message) do
@@ -1,6 +1,5 @@
1
- require 'celluloid'
2
-
3
1
  require 'sidekiq/util'
2
+ require 'sidekiq/actor'
4
3
  require 'sidekiq/processor'
5
4
  require 'sidekiq/fetch'
6
5
 
@@ -13,10 +12,13 @@ module Sidekiq
13
12
  #
14
13
  class Manager
15
14
  include Util
16
- include Celluloid
17
-
15
+ include Actor
18
16
  trap_exit :processor_died
19
17
 
18
+ attr_reader :ready
19
+ attr_reader :busy
20
+ attr_accessor :fetcher
21
+
20
22
  def initialize(options={})
21
23
  logger.debug { options.inspect }
22
24
  @count = options[:concurrency] || 25
@@ -122,6 +124,8 @@ module Sidekiq
122
124
  end
123
125
  conn.srem('workers', workers_to_remove) if !workers_to_remove.empty?
124
126
  end
127
+ rescue => ex
128
+ Sidekiq.logger.warn("Unable to clear worker set while shutting down: #{ex.message}")
125
129
  end
126
130
 
127
131
  def hard_shutdown_in(delay)
@@ -48,6 +48,9 @@ module Sidekiq
48
48
 
49
49
  def call(worker, msg, queue)
50
50
  yield
51
+ rescue Sidekiq::Shutdown
52
+ # ignore, will be pushed back onto queue
53
+ raise
51
54
  rescue Exception => e
52
55
  raise e unless msg['retry']
53
56
  max_retry_attempts = retry_attempts_from(msg['retry'], DEFAULT_MAX_RETRY_ATTEMPTS)
@@ -1,5 +1,5 @@
1
- require 'celluloid'
2
1
  require 'sidekiq/util'
2
+ require 'sidekiq/actor'
3
3
 
4
4
  require 'sidekiq/middleware/server/active_record'
5
5
  require 'sidekiq/middleware/server/retry_jobs'
@@ -12,7 +12,9 @@ module Sidekiq
12
12
  # chain and then calls Sidekiq::Worker#perform.
13
13
  class Processor
14
14
  include Util
15
- include Celluloid
15
+ include Actor
16
+
17
+ task_class TaskThread
16
18
 
17
19
  def self.default_middleware
18
20
  Middleware::Chain.new do |m|
@@ -34,29 +36,29 @@ module Sidekiq
34
36
  def process(work)
35
37
  msgstr = work.message
36
38
  queue = work.queue_name
37
- defer do
38
- @actual_work_thread = Thread.current
39
- begin
40
- msg = Sidekiq.load_json(msgstr)
41
- klass = msg['class'].constantize
42
- worker = klass.new
43
- worker.jid = msg['jid']
44
-
45
- stats(worker, msg, queue) do
46
- Sidekiq.server_middleware.invoke(worker, msg, queue) do
47
- worker.perform(*cloned(msg['args']))
48
- end
39
+
40
+ @actual_work_thread = Thread.current
41
+ begin
42
+ msg = Sidekiq.load_json(msgstr)
43
+ klass = msg['class'].constantize
44
+ worker = klass.new
45
+ worker.jid = msg['jid']
46
+
47
+ stats(worker, msg, queue) do
48
+ Sidekiq.server_middleware.invoke(worker, msg, queue) do
49
+ worker.perform(*cloned(msg['args']))
49
50
  end
50
- rescue Sidekiq::Shutdown
51
- # Had to force kill this job because it didn't finish
52
- # within the timeout.
53
- rescue Exception => ex
54
- handle_exception(ex, msg || { :message => msgstr })
55
- raise
56
- ensure
57
- work.acknowledge
58
51
  end
52
+ rescue Sidekiq::Shutdown
53
+ # Had to force kill this job because it didn't finish
54
+ # within the timeout.
55
+ rescue Exception => ex
56
+ handle_exception(ex, msg || { :message => msgstr })
57
+ raise
58
+ ensure
59
+ work.acknowledge
59
60
  end
61
+
60
62
  @boss.async.processor_done(current_actor)
61
63
  end
62
64
 
@@ -1,6 +1,6 @@
1
1
  require 'sidekiq'
2
2
  require 'sidekiq/util'
3
- require 'celluloid'
3
+ require 'sidekiq/actor'
4
4
 
5
5
  module Sidekiq
6
6
  module Scheduled
@@ -13,8 +13,8 @@ module Sidekiq
13
13
  # just pops the message back onto its original queue so the
14
14
  # workers can pick it up like any other message.
15
15
  class Poller
16
- include Celluloid
17
- include Sidekiq::Util
16
+ include Util
17
+ include Actor
18
18
 
19
19
  SETS = %w(retry schedule)
20
20
 
@@ -42,7 +42,7 @@ module Sidekiq
42
42
  conn.sadd('queues', msg['queue'])
43
43
  conn.lpush("queue:#{msg['queue']}", message)
44
44
  end
45
- logger.debug("enqueued #{sorted_set}: #{message}") if logger.debug?
45
+ logger.debug { "enqueued #{sorted_set}: #{message}" }
46
46
  end
47
47
  end
48
48
  end
@@ -51,7 +51,7 @@ module Sidekiq
51
51
  # Most likely a problem with redis networking.
52
52
  # Punt and try again at the next interval
53
53
  logger.error ex.message
54
- logger.error(ex.backtrace.first)
54
+ logger.error ex.backtrace.first
55
55
  end
56
56
 
57
57
  after(poll_interval) { poll }
@@ -1,3 +1,3 @@
1
1
  module Sidekiq
2
- VERSION = "2.11.2"
2
+ VERSION = "2.12.0"
3
3
  end
@@ -17,11 +17,11 @@ Gem::Specification.new do |gem|
17
17
  gem.add_dependency 'redis', '>= 3.0'
18
18
  gem.add_dependency 'redis-namespace'
19
19
  gem.add_dependency 'connection_pool', '>= 1.0.0'
20
- gem.add_dependency 'celluloid', '>= 0.13.0'
21
- gem.add_dependency 'multi_json'
20
+ gem.add_dependency 'celluloid', '>= 0.14.0'
21
+ gem.add_dependency 'json'
22
22
  gem.add_development_dependency 'sinatra'
23
23
  gem.add_development_dependency 'slim'
24
- gem.add_development_dependency 'minitest'
24
+ gem.add_development_dependency 'minitest', '~> 5'
25
25
  gem.add_development_dependency 'rake'
26
26
  gem.add_development_dependency 'actionmailer'
27
27
  gem.add_development_dependency 'activerecord'
@@ -1,3 +1,4 @@
1
+ $TESTING = true
1
2
  require 'coveralls'
2
3
  Coveralls.wear! do
3
4
  add_filter "/test/"
@@ -16,13 +17,17 @@ begin
16
17
  rescue LoadError
17
18
  end
18
19
 
19
- require 'minitest/unit'
20
20
  require 'minitest/autorun'
21
- require 'minitest/emoji'
21
+ require 'minitest/pride'
22
22
 
23
23
  require 'sidekiq'
24
24
  require 'sidekiq/util'
25
25
  Sidekiq.logger.level = Logger::ERROR
26
26
 
27
27
  require 'sidekiq/redis_connection'
28
- REDIS = Sidekiq::RedisConnection.create(:url => "redis://localhost/15", :namespace => 'testy')
28
+ redis_url = ENV['REDIS_URL'] || 'redis://localhost/15'
29
+ REDIS = Sidekiq::RedisConnection.create(:url => redis_url, :namespace => 'testy')
30
+
31
+ Sidekiq.configure_client do |config|
32
+ config.redis = { :url => redis_url, :namespace => 'testy' }
33
+ end
@@ -1,6 +1,6 @@
1
1
  require 'helper'
2
2
 
3
- class TestApi < MiniTest::Unit::TestCase
3
+ class TestApi < Minitest::Test
4
4
  describe "stats" do
5
5
  before do
6
6
  Sidekiq.redis {|c| c.flushdb }
@@ -11,7 +11,7 @@ def cli.valid?
11
11
  !@code
12
12
  end
13
13
 
14
- class TestCli < MiniTest::Unit::TestCase
14
+ class TestCli < Minitest::Test
15
15
  describe 'with cli' do
16
16
 
17
17
  before do
@@ -2,10 +2,10 @@ require 'helper'
2
2
  require 'sidekiq/client'
3
3
  require 'sidekiq/worker'
4
4
 
5
- class TestClient < MiniTest::Unit::TestCase
5
+ class TestClient < Minitest::Test
6
6
  describe 'with mock redis' do
7
7
  before do
8
- @redis = MiniTest::Mock.new
8
+ @redis = Minitest::Mock.new
9
9
  def @redis.multi; [yield] * 2 if block_given?; end
10
10
  def @redis.set(*); true; end
11
11
  def @redis.sadd(*); true; end
@@ -22,6 +22,10 @@ class TestClient < MiniTest::Unit::TestCase
22
22
  Sidekiq.instance_variable_set(:@redis, @redis)
23
23
  end
24
24
 
25
+ after do
26
+ Sidekiq.instance_variable_set(:@redis, REDIS)
27
+ end
28
+
25
29
  it 'raises ArgumentError with invalid params' do
26
30
  assert_raises ArgumentError do
27
31
  Sidekiq::Client.push('foo', 1)
@@ -17,7 +17,7 @@ class Component
17
17
  end
18
18
  end
19
19
 
20
- class TestExceptionHandler < MiniTest::Unit::TestCase
20
+ class TestExceptionHandler < Minitest::Test
21
21
  describe "with mock logger" do
22
22
  before do
23
23
  @old_logger = Sidekiq.logger
@@ -41,7 +41,7 @@ class TestExceptionHandler < MiniTest::Unit::TestCase
41
41
 
42
42
  describe "with fake Airbrake" do
43
43
  before do
44
- ::Airbrake = MiniTest::Mock.new
44
+ ::Airbrake = Minitest::Mock.new
45
45
  end
46
46
 
47
47
  after do
@@ -57,7 +57,7 @@ class TestExceptionHandler < MiniTest::Unit::TestCase
57
57
 
58
58
  describe "with fake Honeybadger" do
59
59
  before do
60
- ::Honeybadger = MiniTest::Mock.new
60
+ ::Honeybadger = Minitest::Mock.new
61
61
  end
62
62
 
63
63
  after do
@@ -73,8 +73,7 @@ class TestExceptionHandler < MiniTest::Unit::TestCase
73
73
 
74
74
  describe "with fake ExceptionNotifier" do
75
75
  before do
76
- ::ExceptionNotifier = Module.new
77
- ::ExceptionNotifier::Notifier = MiniTest::Mock.new
76
+ ::ExceptionNotifier = Minitest::Mock.new
78
77
  end
79
78
 
80
79
  after do
@@ -82,12 +81,9 @@ class TestExceptionHandler < MiniTest::Unit::TestCase
82
81
  end
83
82
 
84
83
  it "notifies ExceptionNotifier" do
85
- mail = MiniTest::Mock.new
86
- mail.expect(:deliver,nil)
87
- ::ExceptionNotifier::Notifier.expect(:background_exception_notification,mail,[TEST_EXCEPTION, :data => { :message => { :b => 2 } }])
84
+ ::ExceptionNotifier.expect(:notify_exception,nil,[TEST_EXCEPTION, :data => { :message => { :b => 2 } }])
88
85
  Component.new.invoke_exception(:b => 2)
89
- ::ExceptionNotifier::Notifier.verify
90
- mail.verify
86
+ ::ExceptionNotifier.verify
91
87
  end
92
88
  end
93
89
 
@@ -104,9 +100,9 @@ class TestExceptionHandler < MiniTest::Unit::TestCase
104
100
  end
105
101
  end
106
102
 
107
- ::Exceptional::Config = MiniTest::Mock.new
108
- ::Exceptional::Remote = MiniTest::Mock.new
109
- ::Exceptional::ExceptionData = MiniTest::Mock.new
103
+ ::Exceptional::Config = Minitest::Mock.new
104
+ ::Exceptional::Remote = Minitest::Mock.new
105
+ ::Exceptional::ExceptionData = Minitest::Mock.new
110
106
  end
111
107
 
112
108
  after do
@@ -8,7 +8,7 @@ require 'sidekiq/rails'
8
8
 
9
9
  Sidekiq.hook_rails!
10
10
 
11
- class TestExtensions < MiniTest::Unit::TestCase
11
+ class TestExtensions < Minitest::Test
12
12
  describe 'sidekiq extensions' do
13
13
  before do
14
14
  Sidekiq.redis = REDIS
@@ -1,7 +1,7 @@
1
1
  require 'helper'
2
2
  require 'sidekiq/fetch'
3
3
 
4
- class TestFetcher < MiniTest::Unit::TestCase
4
+ class TestFetcher < Minitest::Test
5
5
  describe 'fetcher' do
6
6
  before do
7
7
  Sidekiq.redis = { :namespace => 'fuzzy' }
@@ -0,0 +1,90 @@
1
+ require 'helper'
2
+ require 'sidekiq/manager'
3
+
4
+ class TestManager < Minitest::Test
5
+
6
+ describe 'manager' do
7
+ it 'creates N processor instances' do
8
+ mgr = Sidekiq::Manager.new(options)
9
+ assert_equal options[:concurrency], mgr.ready.size
10
+ assert_equal [], mgr.busy
11
+ assert mgr.fetcher
12
+ end
13
+
14
+ it 'fetches upon start' do
15
+ mgr = Sidekiq::Manager.new(options)
16
+ count = options[:concurrency]
17
+
18
+ fetch_mock = Minitest::Mock.new
19
+ count.times { fetch_mock.expect(:fetch, nil, []) }
20
+ async_mock = Minitest::Mock.new
21
+ count.times { async_mock.expect(:async, fetch_mock, []) }
22
+ mgr.fetcher = async_mock
23
+ mgr.start
24
+
25
+ fetch_mock.verify
26
+ async_mock.verify
27
+ end
28
+
29
+ it 'assigns work to a processor' do
30
+ uow = Minitest::Mock.new
31
+ processor = Minitest::Mock.new
32
+ processor.expect(:async, processor, [])
33
+ processor.expect(:process, nil, [uow])
34
+
35
+ mgr = Sidekiq::Manager.new(options)
36
+ mgr.ready << processor
37
+ mgr.assign(uow)
38
+ assert_equal 1, mgr.busy.size
39
+
40
+ processor.verify
41
+ end
42
+
43
+ it 'requeues work if stopping' do
44
+ uow = Minitest::Mock.new
45
+ uow.expect(:requeue, nil, [])
46
+
47
+ mgr = Sidekiq::Manager.new(options)
48
+ mgr.stop
49
+ mgr.assign(uow)
50
+ uow.verify
51
+ end
52
+
53
+ it 'shuts down the system' do
54
+ mgr = Sidekiq::Manager.new(options)
55
+ mgr.stop
56
+
57
+ assert mgr.busy.empty?
58
+ assert mgr.ready.empty?
59
+ refute mgr.fetcher.alive?
60
+ end
61
+
62
+ it 'returns finished processors to the ready pool' do
63
+ mgr = Sidekiq::Manager.new(options)
64
+ init_size = mgr.ready.size
65
+ processor = mgr.ready.pop
66
+ mgr.busy << processor
67
+ mgr.processor_done(processor)
68
+
69
+ assert_equal 0, mgr.busy.size
70
+ assert_equal init_size, mgr.ready.size
71
+ end
72
+
73
+ it 'throws away dead processors' do
74
+ mgr = Sidekiq::Manager.new(options)
75
+ init_size = mgr.ready.size
76
+ processor = mgr.ready.pop
77
+ mgr.busy << processor
78
+ mgr.processor_died(processor, 'ignored')
79
+
80
+ assert_equal 0, mgr.busy.size
81
+ assert_equal init_size, mgr.ready.size
82
+ refute mgr.ready.include?(processor)
83
+ end
84
+
85
+ def options
86
+ { :concurrency => 3, :queues => ['default'] }
87
+ end
88
+ end
89
+
90
+ end
@@ -2,7 +2,7 @@ require 'helper'
2
2
  require 'sidekiq/middleware/chain'
3
3
  require 'sidekiq/processor'
4
4
 
5
- class TestMiddleware < MiniTest::Unit::TestCase
5
+ class TestMiddleware < Minitest::Test
6
6
  describe 'middleware chain' do
7
7
  before do
8
8
  $errors = []
@@ -78,9 +78,9 @@ class TestMiddleware < MiniTest::Unit::TestCase
78
78
  chain.insert_after AnotherCustomMiddleware, YetAnotherCustomMiddleware, '3', $recorder
79
79
  end
80
80
 
81
- boss = MiniTest::Mock.new
81
+ boss = Minitest::Mock.new
82
82
  processor = Sidekiq::Processor.new(boss)
83
- actor = MiniTest::Mock.new
83
+ actor = Minitest::Mock.new
84
84
  actor.expect(:processor_done, nil, [processor])
85
85
  boss.expect(:async, actor, [])
86
86
  processor.process(Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg))
@@ -1,14 +1,14 @@
1
1
  require 'helper'
2
2
  require 'sidekiq/processor'
3
3
 
4
- class TestProcessor < MiniTest::Unit::TestCase
4
+ class TestProcessor < Minitest::Test
5
5
  TestException = Class.new(StandardError)
6
6
  TEST_EXCEPTION = TestException.new("kerboom!")
7
7
 
8
8
  describe 'with mock setup' do
9
9
  before do
10
10
  $invokes = 0
11
- @boss = MiniTest::Mock.new
11
+ @boss = Minitest::Mock.new
12
12
  @processor = ::Sidekiq::Processor.new(@boss)
13
13
  Celluloid.logger = nil
14
14
  Sidekiq.redis = REDIS
@@ -29,7 +29,7 @@ class TestProcessor < MiniTest::Unit::TestCase
29
29
 
30
30
  it 'processes as expected' do
31
31
  msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
32
- actor = MiniTest::Mock.new
32
+ actor = Minitest::Mock.new
33
33
  actor.expect(:processor_done, nil, [@processor])
34
34
  @boss.expect(:async, actor, [])
35
35
  @processor.process(work(msg))
@@ -65,7 +65,7 @@ class TestProcessor < MiniTest::Unit::TestCase
65
65
  msg = { 'class' => MockWorker.to_s, 'args' => [['myarg']] }
66
66
  msgstr = Sidekiq.dump_json(msg)
67
67
  processor = ::Sidekiq::Processor.new(@boss)
68
- actor = MiniTest::Mock.new
68
+ actor = Minitest::Mock.new
69
69
  actor.expect(:processor_done, nil, [processor])
70
70
  @boss.expect(:async, actor, [])
71
71
  processor.process(work(msgstr))
@@ -80,7 +80,7 @@ class TestProcessor < MiniTest::Unit::TestCase
80
80
  describe 'when successful' do
81
81
  def successful_job
82
82
  msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
83
- actor = MiniTest::Mock.new
83
+ actor = Minitest::Mock.new
84
84
  actor.expect(:processor_done, nil, [@processor])
85
85
  @boss.expect(:async, actor, [])
86
86
  @processor.process(work(msg))
@@ -1,7 +1,7 @@
1
1
  require 'helper'
2
2
  require 'sidekiq/redis_connection'
3
3
 
4
- class TestRedisConnection < MiniTest::Unit::TestCase
4
+ class TestRedisConnection < Minitest::Test
5
5
 
6
6
  describe ".create" do
7
7
 
@@ -2,10 +2,10 @@ require 'helper'
2
2
  require 'sidekiq/scheduled'
3
3
  require 'sidekiq/middleware/server/retry_jobs'
4
4
 
5
- class TestRetry < MiniTest::Unit::TestCase
5
+ class TestRetry < Minitest::Test
6
6
  describe 'middleware' do
7
7
  before do
8
- @redis = MiniTest::Mock.new
8
+ @redis = Minitest::Mock.new
9
9
  # Ugh, this is terrible.
10
10
  Sidekiq.instance_variable_set(:@redis, @redis)
11
11
 
@@ -150,7 +150,7 @@ class TestRetry < MiniTest::Unit::TestCase
150
150
  raise "kerblammo!"
151
151
  end
152
152
  end
153
- # MiniTest can't assert that a method call did NOT happen!?
153
+ # Minitest can't assert that a method call did NOT happen!?
154
154
  assert_raises(MockExpectationError) { @redis.verify }
155
155
  end
156
156
 
@@ -164,12 +164,12 @@ class TestRetry < MiniTest::Unit::TestCase
164
164
  raise "kerblammo!"
165
165
  end
166
166
  end
167
- # MiniTest can't assert that a method call did NOT happen!?
167
+ # Minitest can't assert that a method call did NOT happen!?
168
168
  assert_raises(MockExpectationError) { @redis.verify }
169
169
  end
170
170
 
171
171
  describe "retry exhaustion" do
172
- let(:worker){ MiniTest::Mock.new }
172
+ let(:worker){ Minitest::Mock.new }
173
173
  let(:handler){ Sidekiq::Middleware::Server::RetryJobs.new }
174
174
  let(:msg){ {"class"=>"Bob", "args"=>[1, 2, "foo"], "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>Time.now.utc, "retry"=>3, "retry_count"=>3} }
175
175
 
@@ -1,13 +1,13 @@
1
1
  require 'helper'
2
2
  require 'sidekiq/scheduled'
3
3
 
4
- class TestScheduled < MiniTest::Unit::TestCase
4
+ class TestScheduled < Minitest::Test
5
5
  class ScheduledWorker
6
6
  include Sidekiq::Worker
7
7
  def perform(x)
8
8
  end
9
9
  end
10
-
10
+
11
11
  describe 'poller' do
12
12
  before do
13
13
  Sidekiq.redis = REDIS
@@ -34,8 +34,7 @@ class TestScheduled < MiniTest::Unit::TestCase
34
34
 
35
35
  poller = Sidekiq::Scheduled::Poller.new
36
36
  poller.poll
37
- poller.terminate
38
-
37
+
39
38
  assert_equal [error_1], conn.lrange("queue:queue_1", 0, -1)
40
39
  assert_equal [error_2], conn.lrange("queue:queue_2", 0, -1)
41
40
  assert_equal [error_3], conn.zrange("retry", 0, -1)
@@ -1,10 +1,10 @@
1
1
  require 'helper'
2
2
  require 'sidekiq/scheduled'
3
3
 
4
- class TestScheduling < MiniTest::Unit::TestCase
4
+ class TestScheduling < Minitest::Test
5
5
  describe 'middleware' do
6
6
  before do
7
- @redis = MiniTest::Mock.new
7
+ @redis = Minitest::Mock.new
8
8
  # Ugh, this is terrible.
9
9
  Sidekiq.instance_variable_set(:@redis, @redis)
10
10
 
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'helper'
3
3
 
4
- class TestSidekiq < MiniTest::Unit::TestCase
4
+ class TestSidekiq < Minitest::Test
5
5
  describe 'json processing' do
6
6
  it 'loads json' do
7
7
  assert_equal ({"foo" => "bar"}), Sidekiq.load_json("{\"foo\":\"bar\"}")
@@ -14,7 +14,7 @@ class TestSidekiq < MiniTest::Unit::TestCase
14
14
 
15
15
  describe "redis connection" do
16
16
  it "returns error without creating a connection if block is not given" do
17
- mock = MiniTest::Mock.new
17
+ mock = Minitest::Mock.new
18
18
  mock.expect :create, nil #Sidekiq::RedisConnection, create
19
19
  assert_raises(ArgumentError) {
20
20
  Sidekiq.redis
@@ -9,7 +9,7 @@ require 'sidekiq/extensions/active_record'
9
9
 
10
10
  Sidekiq.hook_rails!
11
11
 
12
- class TestTesting < MiniTest::Unit::TestCase
12
+ class TestTesting < Minitest::Test
13
13
  describe 'sidekiq testing' do
14
14
  class PerformError < RuntimeError; end
15
15
 
@@ -9,7 +9,7 @@ require 'sidekiq/extensions/active_record'
9
9
 
10
10
  Sidekiq.hook_rails!
11
11
 
12
- class TestInline < MiniTest::Unit::TestCase
12
+ class TestInline < Minitest::Test
13
13
  describe 'sidekiq inline testing' do
14
14
  class InlineError < RuntimeError; end
15
15
  class ParameterIsNotString < RuntimeError; end
@@ -3,7 +3,7 @@ require 'sidekiq'
3
3
  require 'sidekiq/web'
4
4
  require 'rack/test'
5
5
 
6
- class TestWeb < MiniTest::Unit::TestCase
6
+ class TestWeb < Minitest::Test
7
7
  describe 'sidekiq web' do
8
8
  include Rack::Test::Methods
9
9
 
@@ -0,0 +1,62 @@
1
+ # elements like %{queue} are variables and should not be translated
2
+ ko:
3
+ Dashboard: 대시보드
4
+ Status: 상태
5
+ Time: 시간
6
+ Namespace: 네임스페이스
7
+ Realtime: 실시간
8
+ History: 히스토리
9
+ Busy: 바쁨
10
+ Processed: 처리완료
11
+ Failed: 실패
12
+ Scheduled: 예약
13
+ Retries: 재시도
14
+ Enqueued: 대기 중
15
+ ClearWorkerList: 워커 목록 비우기
16
+ Worker: 워커
17
+ Workers: 워커
18
+ LivePoll: 폴링 시작
19
+ StopPolling: 폴링 중단
20
+ Queue: 큐
21
+ Class: 클래스
22
+ Job: 작업
23
+ Arguments: 인자
24
+ Started: 시작
25
+ ShowAll: 모두 보기
26
+ CurrentMessagesInQueue: <span class='title'>%{queue}</span>에 대기 중인 메시지
27
+ Delete: 삭제
28
+ AreYouSureDeleteJob: 이 작업을 삭제하시겠습니까?
29
+ AreYouSureDeleteQueue: 이 %{queue} 큐를 삭제하시겠습니까?
30
+ Queues: 큐
31
+ Size: 크기
32
+ Actions: 동작
33
+ NextRetry: 다음 재시도
34
+ RetryCount: 재시도 횟수
35
+ RetryNow: 지금 재시도
36
+ LastRetry: 최근 재시도
37
+ OriginallyFailed: 실패
38
+ AreYouSure: 정말입니까?
39
+ DeleteAll: 모두 삭제
40
+ RetryAll: 모두 재시도
41
+ NoRetriesFound: 재시도 내역이 없습니다
42
+ Error: 에러
43
+ ErrorClass: 에러 클래스
44
+ ErrorMessage: 에러 메시지
45
+ ErrorBacktrace: 에러 Backtrace
46
+ GoBack: ← 뒤로
47
+ NoScheduledFound: 예약된 작업이 없습니다
48
+ When: 언제
49
+ ScheduledJobs: 예약된 작업
50
+ idle: 대기 중
51
+ active: 동작 중
52
+ Version: 버전
53
+ Connections: 커넥션
54
+ MemoryUsage: 메모리 사용량
55
+ PeakMemoryUsage: 최대 메모리 사용량
56
+ Uptime: 업타임 (일)
57
+ OneWeek: 1 주
58
+ OneMonth: 1 달
59
+ ThreeMonths: 3 달
60
+ SixMonths: 6 달
61
+ Batches: 배치
62
+ Failures: 실패
@@ -5,13 +5,12 @@
5
5
  ul.nav
6
6
  - tabs.each do |title, url|
7
7
  - if url == ''
8
- li class="#{(current_path == url) ? 'active':''}"
9
- a href='#{{root_path}}#{{url}}' = t(title)
8
+ li class="#{current_path == url ? 'active' : ''}"
9
+ a href="#{{root_path}}#{{url}}" = t(title)
10
10
  - else
11
- li class="#{(current_path =~ Regexp.new(url)) ? 'active':''}"
12
- a href='#{{root_path}}#{{url}}' = t(title)
11
+ li class="#{current_path.start_with?(url) ? 'active' : ''}"
12
+ a href="#{{root_path}}#{{url}}" = t(title)
13
13
 
14
14
  - custom_tabs.each do |title, url|
15
- li class="#{(current_path =~ Regexp.new(url)) ? 'active':''}"
16
- a href='#{{root_path}}#{{url}}' = t(title)
17
-
15
+ li class="#{current_path.start_with?(url) ? 'active' : ''}"
16
+ a href="#{{root_path}}#{{url}}" = t(title)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.11.2
4
+ version: 2.12.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-01 00:00:00.000000000 Z
12
+ date: 2013-05-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ! '>='
68
68
  - !ruby/object:Gem::Version
69
- version: 0.13.0
69
+ version: 0.14.0
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,9 +74,9 @@ dependencies:
74
74
  requirements:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
- version: 0.13.0
77
+ version: 0.14.0
78
78
  - !ruby/object:Gem::Dependency
79
- name: multi_json
79
+ name: json
80
80
  requirement: !ruby/object:Gem::Requirement
81
81
  none: false
82
82
  requirements:
@@ -128,17 +128,17 @@ dependencies:
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  none: false
130
130
  requirements:
131
- - - ! '>='
131
+ - - ~>
132
132
  - !ruby/object:Gem::Version
133
- version: '0'
133
+ version: '5'
134
134
  type: :development
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
137
137
  none: false
138
138
  requirements:
139
- - - ! '>='
139
+ - - ~>
140
140
  - !ruby/object:Gem::Version
141
- version: '0'
141
+ version: '5'
142
142
  - !ruby/object:Gem::Dependency
143
143
  name: rake
144
144
  requirement: !ruby/object:Gem::Requirement
@@ -218,12 +218,14 @@ files:
218
218
  - Changes.md
219
219
  - Gemfile
220
220
  - LICENSE
221
+ - Pro-Changes.md
221
222
  - README.md
222
223
  - Rakefile
223
224
  - bin/sidekiq
224
225
  - bin/sidekiqctl
225
226
  - config.ru
226
227
  - lib/sidekiq.rb
228
+ - lib/sidekiq/actor.rb
227
229
  - lib/sidekiq/api.rb
228
230
  - lib/sidekiq/capistrano.rb
229
231
  - lib/sidekiq/cli.rb
@@ -266,6 +268,7 @@ files:
266
268
  - test/test_exception_handler.rb
267
269
  - test/test_extensions.rb
268
270
  - test/test_fetch.rb
271
+ - test/test_manager.rb
269
272
  - test/test_middleware.rb
270
273
  - test/test_processor.rb
271
274
  - test/test_redis_connection.rb
@@ -293,6 +296,7 @@ files:
293
296
  - web/locales/fr.yml
294
297
  - web/locales/it.yml
295
298
  - web/locales/ja.yml
299
+ - web/locales/ko.yml
296
300
  - web/locales/nl.yml
297
301
  - web/locales/no.yml
298
302
  - web/locales/pl.yml
@@ -348,6 +352,7 @@ test_files:
348
352
  - test/test_exception_handler.rb
349
353
  - test/test_extensions.rb
350
354
  - test/test_fetch.rb
355
+ - test/test_manager.rb
351
356
  - test/test_middleware.rb
352
357
  - test/test_processor.rb
353
358
  - test/test_redis_connection.rb