Skip to content

Commit

Permalink
Merge branch 'master' into rails5
Browse files Browse the repository at this point in the history
  • Loading branch information
mperham committed Apr 13, 2016
2 parents e9eb6a3 + 637a460 commit eca6424
Show file tree
Hide file tree
Showing 26 changed files with 278 additions and 86 deletions.
File renamed without changes.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ sudo: false
cache: bundler
services:
- redis-server
before_install:
- gem install bundler
- gem update bundler
rvm:
- 2.2.4
- 2.3.0
Expand Down
2 changes: 1 addition & 1 deletion COMM-LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ In order to use the Software under this Agreement, you must receive a “Source

3.1 You shall not (and shall not allow any third party to): (a) decompile, disassemble, or otherwise reverse engineer the Software or attempt to reconstruct or discover any source code, underlying ideas, algorithms, file formats or programming interfaces of the Software by any means whatsoever (except and only to the extent that applicable law prohibits or restricts reverse engineering restrictions); (b) distribute, sell, sublicense, rent, lease or use the Software for time sharing, hosting, service provider or like purposes, except as expressly permitted under this Agreement; (c) redistribute the Software or Modifications other than by including the Software or a portion thereof within your own product, which must have substantially different functionality than the Software or Modifications and must not allow any third party to use the Software or Modifications, or any portions thereof, for software development or application development purposes; (d) redistribute the Software as part of a product, "appliance" or "virtual server"; (e) redistribute the Software on any server which is not directly under your control; (f) remove any product identification, proprietary, copyright or other notices contained in the Software; (g) modify any part of the Software, create a derivative work of any part of the Software (except as permitted in Section 4), or incorporate the Software, except to the extent expressly authorized in writing by Contributed Systems; (h) publicly disseminate performance information or analysis (including, without limitation, benchmarks) from any source relating to the Software; (i) utilize any equipment, device, software, or other means designed to circumvent or remove any form of Source URL or copy protection used by Contributed Systems in connection with the Software, or use the Software together with any authorization code, Source URL, serial number, or other copy protection device not supplied by Contributed Systems; (j) use the Software to develop a product which is competitive with any Contributed Systems product offerings; or (k) use unauthorized Source URLS or keycode(s) or distribute or publish Source URLs or keycode(s), except as may be expressly permitted by Contributed Systems in writing. If your unique Source URL is ever published, Contributed Systems reserves the right to terminate your access without notice.

3.2 UNDER NO CIRCUMSTANCES MAY YOU USE THE SOFTWARE FOR A PRODUCT THAT IS INTENDED FOR SOFTWARE OR APPLICATION DEVELOPMENT PURPOSES.
3.2 UNDER NO CIRCUMSTANCES MAY YOU USE THE SOFTWARE AS PART OF A PRODUCT OR SERVICE THAT PROVIDES SIMILAR FUNCTIONALITY TO THE SOFTWARE ITSELF.

The Open Source version of the Software (“LGPL Version”) is licensed
under the terms of the GNU Lesser General Public License versions 3.0
Expand Down
20 changes: 20 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Sidekiq Changes

4.1.2
-----------

- Client middleware can now stop bulk job push. [#2887]

4.1.1
-----------

- Much better behavior when Redis disappears and comes back. [#2866]
- Update FR locale [dbachet]
- Don't fill logfile in case of Redis downtime [#2860]
- Allow definition of a global retries_exhausted handler. [#2807]
```ruby
Sidekiq.configure_server do |config|
config.default_retries_exhausted = -> (job, ex) do
Sidekiq.logger.info "#{job['class']} job is now dead"
end
end
```

4.1.0
-----------

Expand Down
9 changes: 9 additions & 0 deletions Ent-Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ Sidekiq Enterprise Changelog

Please see [http://sidekiq.org/](http://sidekiq.org/) for more details and how to buy.

1.2.1
-------------

- Multi-Process mode can now monitor the RSS memory of children and
restart any that grow too large. To limit children to 1GB each:
```
MAXMEM_KB=1048576 COUNT=2 bundle exec sidekiqswarm ...
```

1.2.0
-------------

Expand Down
51 changes: 51 additions & 0 deletions Pro-Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,57 @@ Sidekiq Pro Changelog

Please see [http://sidekiq.org/](http://sidekiq.org/) for more details and how to buy.

3.2.1
---------

- timed\_fetch now works with namespaces. [ryansch]


3.2.0
---------

- Fixed detection of missing batches, `NoSuchBatch` should be raised
properly now if `Sidekiq::Batch.new(bid)` is called on a batch no
longer in Redis.
- Remove support for Pro 1.x format batches. This version will no
longer seamlessly process batches created with Sidekiq Pro 1.x.
As always, upgrade one major version at a time to ensure a smooth
transition.
- Fix edge case where a parent batch could expire before a child batch
was finished processing, leading to missing batches [#2889]

2.1.5
---------

- Fix edge case where a parent batch could expire before a child batch
was finished processing, leading to missing batches [#2889]

3.1.0
---------

- New container-friendly fetch algorithm: `timed_fetch`. See the
[wiki documentation](https://github.com/mperham/sidekiq/wiki/Pro-Reliability-Server)
for trade offs between the two reliability options. You should
use this if you are on Heroku, Docker, Amazon ECS or EBS or
another container-based system.


3.0.6
---------

- Fix race condition on reliable fetch shutdown

3.0.5
---------

- Statsd metrics now account for ActiveJob class names
- Allow reliable fetch internals to be overridden [jonhyman]

3.0.4
---------

- Queue pausing no longer requires reliable fetch. [#2786]

3.0.3, 2.1.4
------------

Expand Down
27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Simple, efficient background processing for Ruby.

Sidekiq uses threads to handle many jobs at the same time in the
same process. It does not require Rails but will integrate tightly with
Rails 3/4 to make background processing dead simple.
Rails to make background processing dead simple.

Sidekiq is compatible with Resque. It uses the exact same
message format as Resque so it can integrate into an existing Resque processing farm.
Expand All @@ -31,10 +31,9 @@ DelayedJob 4.1.1 | - | - | 465 sec | 215 jobs/sec
Requirements
-----------------

I test with the latest CRuby (2.2, 2.1 and 2.0) and JRuby versions (9k). Other versions/VMs
are untested but might work fine. CRuby 1.9 is not supported.
Sidekiq supports CRuby 2.0+ and JRuby 9k.

All Rails releases from 3.2 are officially supported.
All Rails releases >= 3.2 are officially supported.

Redis 2.8 or greater is required. 3.0.3+ is recommended for large
installations with thousands of worker threads.
Expand Down Expand Up @@ -63,23 +62,29 @@ features, a commercial-friendly license and allow you to support high
quality open source development all at the same time. Please see the
[Sidekiq](http://sidekiq.org/) homepage for more detail.

Subscribe to the **[quarterly newsletter](https://tinyletter.com/sidekiq)** to stay informed about the latest
features and changes to Sidekiq and its bigger siblings.


Problems?
-----------------

**Please do not directly email any Sidekiq committers with questions or problems.** A community is best served when discussions are held in public.

Please see the [sidekiq wiki](https://github.com/mperham/sidekiq/wiki) for the official documentation.
[mperham/sidekiq on Gitter](https://gitter.im/mperham/sidekiq) is dedicated to this project,
but bug reports or feature requests suggestions should still go through [issues on Github](https://github.com/mperham/sidekiq/issues). Release announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account. **No support via Twitter.**
If you have a problem, please review the [FAQ](https://github.com/mperham/sidekiq/wiki/FAQ) and [Troubleshooting](https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting) wiki pages.
Searching the [issues](https://github.com/mperham/sidekiq/issues) for your problem is also a good idea.

Every Friday morning is Sidekiq happy hour: I video chat and answer questions.
See the [Sidekiq support page](http://sidekiq.org/support).
Useful resources:

You may also find useful a [Reddit area](https://reddit.com/r/sidekiq) dedicated to Sidekiq discussion and [a Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow.
* Product documentation is in the [wiki](https://github.com/mperham/sidekiq/wiki).
* Release announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account.
* Here's a [Reddit forum](https://reddit.com/r/sidekiq) dedicated to Sidekiq discussion
* The [Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow has lots of useful Q & A.

If you have a problem, please review the [FAQ](https://github.com/mperham/sidekiq/wiki/FAQ) and [Troubleshooting](https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting) wiki pages. Searching the issues for your problem is also a good idea. If that doesn't help, feel free to email the Sidekiq mailing list, chat in Gitter, or open a new issue. StackOverflow or Reddit is the preferred place to ask questions on usage. If you are encountering what you think is a bug, please open an issue.
**No support via Twitter, 140 characters is not enough.**

Every Friday morning 9am Pacific is Sidekiq happy hour: I video chat and answer questions.
See the [Sidekiq support page](http://sidekiq.org/support).

Thanks
-----------------
Expand Down
43 changes: 38 additions & 5 deletions lib/sidekiq.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# encoding: utf-8
require 'sidekiq/version'
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby 1.9." if RUBY_PLATFORM != 'java' && RUBY_VERSION < '2.0.0'
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.0.0." if RUBY_PLATFORM != 'java' && RUBY_VERSION < '2.0.0'

require 'sidekiq/logging'
require 'sidekiq/client'
Expand Down Expand Up @@ -38,14 +38,21 @@ module Sidekiq
'queue' => 'default'
}

FAKE_INFO = {
"redis_version" => "9.9.9",
"uptime_in_days" => "9999",
"connected_clients" => "9999",
"used_memory_human" => "9P",
"used_memory_peak_human" => "9P"
}.freeze

def self.❨╯°□°❩╯︵┻━┻
puts "Calm down, yo."
end

def self.options
@options ||= DEFAULTS.dup
end

def self.options=(opts)
@options = opts
end
Expand Down Expand Up @@ -92,6 +99,24 @@ def self.redis
end
end

def self.redis_info
redis do |conn|
begin
# admin commands can't go through redis-namespace starting
# in redis-namespace 2.0
if conn.respond_to?(:namespace)
conn.redis.info
else
conn.info
end
rescue Redis::CommandError => ex
#2850 return fake version when INFO command has (probably) been renamed
raise unless ex.message =~ /unknown command/
FAKE_INFO
end
end
end

def self.redis_pool
@redis ||= Sidekiq::RedisConnection.create
end
Expand Down Expand Up @@ -133,23 +158,31 @@ def self.default_server_middleware
def self.default_worker_options=(hash)
@default_worker_options = default_worker_options.merge(hash.stringify_keys)
end

def self.default_worker_options
defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
end

# Sidekiq.configure_server do |config|
# config.default_retries_exhausted = -> (job, ex) do
# end
# end
def self.default_retries_exhausted=(prok)
@default_retries_exhausted = prok
end
def self.default_retries_exhausted
@default_retries_exhausted
end

def self.load_json(string)
JSON.parse(string)
end

def self.dump_json(object)
JSON.generate(object)
end

def self.logger
Sidekiq::Logging.logger
end

def self.logger=(log)
Sidekiq::Logging.logger = log
end
Expand Down
1 change: 1 addition & 0 deletions lib/sidekiq/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ def clear
#
class Job
attr_reader :item
attr_reader :value

def initialize(item, queue_name=nil)
@value = item
Expand Down
10 changes: 4 additions & 6 deletions lib/sidekiq/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,10 @@ def run
logger.info Sidekiq::LICENSE
logger.info "Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org" unless defined?(::Sidekiq::Pro)

Sidekiq.redis do |conn|
# touch the connection pool so it is created before we
# fire startup and start multithreading.
ver = conn.info['redis_version']
raise "You are using Redis v#{ver}, Sidekiq requires Redis v2.8.0 or greater" if ver < '2.8'
end
# touch the connection pool so it is created before we
# fire startup and start multithreading.
ver = Sidekiq.redis_info['redis_version']
raise "You are using Redis v#{ver}, Sidekiq requires Redis v2.8.0 or greater" if ver < '2.8'

# Before this point, the process is initializing with just the main thread.
# Starting here the process will now have multiple threads running.
Expand Down
12 changes: 9 additions & 3 deletions lib/sidekiq/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ def push(item)
# Returns an array of the of pushed jobs' jids. The number of jobs pushed can be less
# than the number given if the middleware stopped processing for one or more jobs.
def push_bulk(items)
arg = items['args'].first
raise ArgumentError, "Bulk arguments must be an Array of Arrays: [[1], [2]]" if !arg.is_a?(Array)

normed = normalize_item(items)
payloads = items['args'].map do |args|
raise ArgumentError, "Bulk arguments must be an Array of Arrays: [[1], [2]]" if !args.is_a?(Array)
process_single(items['class'], normed.merge('args' => args, 'jid' => SecureRandom.hex(12), 'enqueued_at' => Time.now.to_f))
copy = normed.merge('args' => args, 'jid' => SecureRandom.hex(12), 'enqueued_at' => Time.now.to_f)
result = process_single(items['class'], copy)
result ? result : nil
end.compact

raw_push(payloads) if !payloads.empty?
Expand All @@ -106,7 +110,8 @@ def push_bulk(items)
# you cannot scale any other way (e.g. splitting your app into smaller apps).
def self.via(pool)
raise ArgumentError, "No pool given" if pool.nil?
raise RuntimeError, "Sidekiq::Client.via is not re-entrant" if x = Thread.current[:sidekiq_via_pool] && x != pool
current_sidekiq_pool = Thread.current[:sidekiq_via_pool]
raise RuntimeError, "Sidekiq::Client.via is not re-entrant" if current_sidekiq_pool && current_sidekiq_pool != pool
Thread.current[:sidekiq_via_pool] = pool
yield
ensure
Expand Down Expand Up @@ -205,6 +210,7 @@ def normalize_item(item)
raise(ArgumentError, "Job must be a Hash with 'class' and 'args' keys: { 'class' => SomeWorker, 'args' => ['bob', 1, :foo => 'bar'] }") unless item.is_a?(Hash) && item.has_key?('class'.freeze) && item.has_key?('args'.freeze)
raise(ArgumentError, "Job args must be an Array") unless item['args'].is_a?(Array)
raise(ArgumentError, "Job class must be either a Class or String representation of the class name") unless item['class'.freeze].is_a?(Class) || item['class'.freeze].is_a?(String)
#raise(ArgumentError, "Arguments must be native JSON types, see https://github.com/mperham/sidekiq/wiki/Best-Practices") unless JSON.load(JSON.dump(item['args'])) == item['args']

normalized_hash(item['class'.freeze])
.each{ |key, value| item[key] = value if item[key].nil? }
Expand Down
3 changes: 2 additions & 1 deletion lib/sidekiq/logging.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'time'
require 'logger'
require 'fcntl'

module Sidekiq
module Logging
Expand Down Expand Up @@ -46,7 +47,7 @@ def self.logger
end

def self.logger=(log)
@logger = (log ? log : Logger.new('/dev/null'))
@logger = (log ? log : Logger.new(File::NULL))
end

# This reopens ALL logfiles in the process that have been rotated
Expand Down
7 changes: 3 additions & 4 deletions lib/sidekiq/middleware/server/retry_jobs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,10 @@ def attempt_retry(worker, msg, queue, exception)
end

def retries_exhausted(worker, msg, exception)
logger.debug { "Dropping message after hitting the retry maximum: #{msg}" }
logger.debug { "Retries exhausted for job" }
begin
if worker.sidekiq_retries_exhausted_block?
worker.sidekiq_retries_exhausted_block.call(msg, exception)
end
block = worker.sidekiq_retries_exhausted_block || Sidekiq.default_retries_exhausted
block.call(msg, exception) if block
rescue => e
handle_exception(e, { context: "Error calling retries_exhausted for #{worker.class}", job: msg })
end
Expand Down
1 change: 1 addition & 0 deletions lib/sidekiq/processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def handle_fetch_exception(ex)
end
end
sleep(1)
nil
end

def process(work)
Expand Down
11 changes: 10 additions & 1 deletion lib/sidekiq/scheduled.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ def enqueue
# Most likely a problem with redis networking.
# Punt and try again at the next interval
logger.error ex.message
logger.error ex.backtrace.first
ex.backtrace.each do |bt|
logger.error(bt)
end
end
end

Expand All @@ -86,6 +88,13 @@ def enqueue
def wait
@sleeper.pop(random_poll_interval)
rescue Timeout::Error
# expected
rescue => ex
# if poll_interval_average hasn't been calculated yet, we can
# raise an error trying to reach Redis.
logger.error ex.message
logger.error ex.backtrace.first
sleep 5
end

# Calculates a random interval that is ±50% the desired average.
Expand Down
Loading

0 comments on commit eca6424

Please sign in to comment.