sidekiq 5.0.0 → 5.0.1
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.
- checksums.yaml +4 -4
- data/COMM-LICENSE +1 -1
- data/Changes.md +12 -1
- data/Ent-Changes.md +21 -0
- data/Pro-Changes.md +3 -1
- data/README.md +1 -1
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +1 -1
- data/lib/sidekiq.rb +2 -2
- data/lib/sidekiq/api.rb +31 -8
- data/lib/sidekiq/cli.rb +3 -1
- data/lib/sidekiq/client.rb +2 -0
- data/lib/sidekiq/core_ext.rb +1 -119
- data/lib/sidekiq/job_logger.rb +7 -10
- data/lib/sidekiq/job_retry.rb +1 -1
- data/lib/sidekiq/logging.rb +12 -0
- data/lib/sidekiq/processor.rb +11 -7
- data/lib/sidekiq/rails.rb +0 -9
- data/lib/sidekiq/redis_connection.rb +3 -1
- data/lib/sidekiq/testing.rb +11 -2
- data/lib/sidekiq/util.rb +0 -1
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +2 -2
- data/lib/sidekiq/web/helpers.rb +43 -14
- data/lib/sidekiq/worker.rb +64 -5
- data/web/assets/javascripts/dashboard.js +7 -0
- data/web/views/_footer.erb +1 -1
- data/web/views/busy.erb +5 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04414e0337f9a41c13f324892ee670396e99ff89
|
4
|
+
data.tar.gz: ca4f4c23c886511caf5699b6e4dffba02c5c721a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d55706e0ffb62246ba056607a7b3ce6c35cad7d18fcc0bff277d4de89f87cecd64e81a373c9dacc9add59604036fed55c0e66ebf9fa62ca2c8b6da553db60e13
|
7
|
+
data.tar.gz: c66998d5104c7c5fa0c22034b9c7b97ad685a3bc14f65b72812ef3c59fbf01799b81304da6e39806bd49661129629ed8ad2619fae29b4b3d04b7f9225403fbfd
|
data/COMM-LICENSE
CHANGED
@@ -38,7 +38,7 @@ under the terms of the GNU Lesser General Public License versions 3.0
|
|
38
38
|
|
39
39
|
5. Fees and Payment. The Software license fees will be due and payable in full as set forth in the applicable invoice or at the time of purchase. If the Software does not function properly within two weeks of purchase, please contact us within those two weeks for a refund. You shall be responsible for all taxes, withholdings, duties and levies arising from the order (excluding taxes based on the net income of Contributed Systems).
|
40
40
|
|
41
|
-
6. Support, Maintenance and Services. Subject to the terms and conditions of this Agreement, as set forth in your invoice, and as set forth on the Sidekiq Pro support page (https://github.com/mperham/sidekiq/wiki/
|
41
|
+
6. Support, Maintenance and Services. Subject to the terms and conditions of this Agreement, as set forth in your invoice, and as set forth on the Sidekiq Pro support page (https://github.com/mperham/sidekiq/wiki/Commercial-Support), support and maintenance services may be included with the purchase of your license subscription.
|
42
42
|
|
43
43
|
7. Term of Agreement.
|
44
44
|
|
data/Changes.md
CHANGED
@@ -2,6 +2,17 @@
|
|
2
2
|
|
3
3
|
[Sidekiq Changes](https://github.com/mperham/sidekiq/blob/master/Changes.md) | [Sidekiq Pro Changes](https://github.com/mperham/sidekiq/blob/master/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/mperham/sidekiq/blob/master/Ent-Changes.md)
|
4
4
|
|
5
|
+
HEAD
|
6
|
+
-----------
|
7
|
+
|
8
|
+
- Fix incorrect server identity when daemonizing [jwilm, #3496]
|
9
|
+
- Work around error running Web UI against Redis Cluster [#3492]
|
10
|
+
- Remove core extensions, Sidekiq is now monkeypatch-free! [#3474]
|
11
|
+
- Reimplement Web UI's HTTP\_ACCEPT\_LANGUAGE parsing because the spec is utterly
|
12
|
+
incomprehensible for various edge cases. [johanlunds, natematykiewicz, #3449]
|
13
|
+
- Update `class_attribute` core extension to avoid warnings
|
14
|
+
- Expose `job_hash_context` from `Sidekiq::Logging` to support log customization
|
15
|
+
|
5
16
|
5.0.0
|
6
17
|
-----------
|
7
18
|
|
@@ -11,7 +22,7 @@
|
|
11
22
|
commonly used public APIs so this shouldn't impact most users.
|
12
23
|
```
|
13
24
|
Sidekiq::Middleware::Server::RetryJobs -> Sidekiq::JobRetry
|
14
|
-
Sidekiq::Middleware::Server::Logging -> Sidekiq::
|
25
|
+
Sidekiq::Middleware::Server::Logging -> Sidekiq::JobLogger
|
15
26
|
```
|
16
27
|
- Quieting Sidekiq is now done via the TSTP signal, the USR1 signal is deprecated.
|
17
28
|
- The `delay` extension APIs are no longer available by default, you
|
data/Ent-Changes.md
CHANGED
@@ -4,6 +4,27 @@
|
|
4
4
|
|
5
5
|
Please see [http://sidekiq.org/](http://sidekiq.org/) for more details and how to buy.
|
6
6
|
|
7
|
+
HEAD
|
8
|
+
-------------
|
9
|
+
|
10
|
+
- Show process "leader" tag on Busy page, requires Sidekiq 5.0.1 [#2867]
|
11
|
+
- Capture custom metrics with the `save_history` API. [#2815]
|
12
|
+
- Implement new `unique_util: 'start'` policy option. [#3471]
|
13
|
+
|
14
|
+
1.5.4
|
15
|
+
-------------
|
16
|
+
|
17
|
+
- Fix broken Cron page in Web UI [#3458]
|
18
|
+
|
19
|
+
1.5.3
|
20
|
+
-------------
|
21
|
+
|
22
|
+
- Remove dependency on the algorithms gem [#3446]
|
23
|
+
- Allow user to specify max memory in megabytes with SIDEKIQ\_MAXMEM\_MB [#3451]
|
24
|
+
- Implement logic to detect app startup failure, sidekiqswarm will exit
|
25
|
+
rather than try to restart the app forever [#3450]
|
26
|
+
- Another fix for doubly-encrypted arguments [#3368]
|
27
|
+
|
7
28
|
1.5.2
|
8
29
|
-------------
|
9
30
|
|
data/Pro-Changes.md
CHANGED
@@ -4,9 +4,11 @@
|
|
4
4
|
|
5
5
|
Please see [http://sidekiq.org/](http://sidekiq.org/) for more details and how to buy.
|
6
6
|
|
7
|
-
|
7
|
+
3.5.0
|
8
8
|
---------
|
9
9
|
|
10
|
+
- Add queue pause/unpause endpoints for scripting via curl [#3445]
|
11
|
+
- Change how super\_fetch names private queues to avoid hostname/queue clashes. [#3443]
|
10
12
|
- Re-implement `Sidekiq::Queue#delete_job` to avoid O(n) runtime [#3408]
|
11
13
|
- Batch page displays Pending JIDs if less than 10 [#3130]
|
12
14
|
- Batch page has a Search button to find associated Retries [#3130]
|
data/README.md
CHANGED
@@ -28,6 +28,7 @@ Sidekiq 3.5.1 | 22ms | 1257 MB | 125 sec | 800 jobs/sec
|
|
28
28
|
Resque 1.25.2 | - | - | 420 sec | 240 jobs/sec
|
29
29
|
DelayedJob 4.1.1 | - | - | 465 sec | 215 jobs/sec
|
30
30
|
|
31
|
+
<small>This benchmark can be found in `bin/sidekiqload`.</small>
|
31
32
|
|
32
33
|
Requirements
|
33
34
|
-----------------
|
@@ -80,7 +81,6 @@ Useful resources:
|
|
80
81
|
|
81
82
|
* Product documentation is in the [wiki](https://github.com/mperham/sidekiq/wiki).
|
82
83
|
* Release announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account.
|
83
|
-
* Here's a [Reddit forum](https://reddit.com/r/sidekiq) dedicated to Sidekiq discussion
|
84
84
|
* The [Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow has lots of useful Q & A.
|
85
85
|
|
86
86
|
**No support via Twitter, 140 characters is not enough.**
|
data/lib/sidekiq.rb
CHANGED
@@ -149,7 +149,8 @@ module Sidekiq
|
|
149
149
|
end
|
150
150
|
|
151
151
|
def self.default_worker_options=(hash)
|
152
|
-
|
152
|
+
# stringify
|
153
|
+
@default_worker_options = default_worker_options.merge(Hash[hash.map{|k, v| [k.to_s, v]}])
|
153
154
|
end
|
154
155
|
def self.default_worker_options
|
155
156
|
defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
|
@@ -222,7 +223,6 @@ module Sidekiq
|
|
222
223
|
# otherwise Ruby's Thread#kill will commit. See #377.
|
223
224
|
# DO NOT RESCUE THIS ERROR IN YOUR WORKERS
|
224
225
|
class Shutdown < Interrupt; end
|
225
|
-
|
226
226
|
end
|
227
227
|
|
228
228
|
require 'sidekiq/rails' if defined?(::Rails::Engine)
|
data/lib/sidekiq/api.rb
CHANGED
@@ -146,11 +146,11 @@ module Sidekiq
|
|
146
146
|
end
|
147
147
|
|
148
148
|
def processed
|
149
|
-
date_stat_hash("processed")
|
149
|
+
@processed ||= date_stat_hash("processed")
|
150
150
|
end
|
151
151
|
|
152
152
|
def failed
|
153
|
-
date_stat_hash("failed")
|
153
|
+
@failed ||= date_stat_hash("failed")
|
154
154
|
end
|
155
155
|
|
156
156
|
private
|
@@ -169,10 +169,15 @@ module Sidekiq
|
|
169
169
|
i += 1
|
170
170
|
end
|
171
171
|
|
172
|
-
|
173
|
-
|
174
|
-
|
172
|
+
begin
|
173
|
+
Sidekiq.redis do |conn|
|
174
|
+
conn.mget(keys).each_with_index do |value, idx|
|
175
|
+
stat_hash[dates[idx]] = value ? value.to_i : 0
|
176
|
+
end
|
175
177
|
end
|
178
|
+
rescue Redis::CommandError
|
179
|
+
# mget will trigger a CROSSSLOT error when run against a Cluster
|
180
|
+
# TODO Someone want to add Cluster support?
|
176
181
|
end
|
177
182
|
|
178
183
|
stat_hash
|
@@ -725,6 +730,11 @@ module Sidekiq
|
|
725
730
|
end
|
726
731
|
|
727
732
|
result.each do |info, busy, at_s, quiet|
|
733
|
+
# If a process is stopped between when we query Redis for `procs` and
|
734
|
+
# when we query for `result`, we will have an item in `result` that is
|
735
|
+
# composed of `nil` values.
|
736
|
+
next if info.nil?
|
737
|
+
|
728
738
|
hash = Sidekiq.load_json(info)
|
729
739
|
yield Process.new(hash.merge('busy' => busy.to_i, 'beat' => at_s.to_f, 'quiet' => quiet))
|
730
740
|
end
|
@@ -740,6 +750,18 @@ module Sidekiq
|
|
740
750
|
def size
|
741
751
|
Sidekiq.redis { |conn| conn.scard('processes') }
|
742
752
|
end
|
753
|
+
|
754
|
+
# Returns the identity of the current cluster leader or "" if no leader.
|
755
|
+
# This is a Sidekiq Enterprise feature, will always return "" in Sidekiq
|
756
|
+
# or Sidekiq Pro.
|
757
|
+
def leader
|
758
|
+
@leader ||= begin
|
759
|
+
x = Sidekiq.redis {|c| c.get("dear-leader") }
|
760
|
+
# need a non-falsy value so we can memoize
|
761
|
+
x = "" unless x
|
762
|
+
x
|
763
|
+
end
|
764
|
+
end
|
743
765
|
end
|
744
766
|
|
745
767
|
#
|
@@ -774,6 +796,10 @@ module Sidekiq
|
|
774
796
|
@attribs[key]
|
775
797
|
end
|
776
798
|
|
799
|
+
def identity
|
800
|
+
self['identity']
|
801
|
+
end
|
802
|
+
|
777
803
|
def quiet!
|
778
804
|
signal('TSTP')
|
779
805
|
end
|
@@ -802,9 +828,6 @@ module Sidekiq
|
|
802
828
|
end
|
803
829
|
end
|
804
830
|
|
805
|
-
def identity
|
806
|
-
self['identity']
|
807
|
-
end
|
808
831
|
end
|
809
832
|
|
810
833
|
##
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -81,6 +81,9 @@ module Sidekiq
|
|
81
81
|
ver = Sidekiq.redis_info['redis_version']
|
82
82
|
raise "You are using Redis v#{ver}, Sidekiq requires Redis v2.8.0 or greater" if ver < '2.8'
|
83
83
|
|
84
|
+
# cache process identity
|
85
|
+
opts[:identity] = identity
|
86
|
+
|
84
87
|
# Touch middleware so it isn't lazy loaded by multiple threads, #3043
|
85
88
|
Sidekiq.server_middleware
|
86
89
|
|
@@ -223,7 +226,6 @@ module Sidekiq
|
|
223
226
|
|
224
227
|
opts[:strict] = true if opts[:strict].nil?
|
225
228
|
opts[:concurrency] = Integer(ENV["RAILS_MAX_THREADS"]) if !opts[:concurrency] && ENV["RAILS_MAX_THREADS"]
|
226
|
-
opts[:identity] = identity
|
227
229
|
|
228
230
|
options.merge!(opts)
|
229
231
|
end
|
data/lib/sidekiq/client.rb
CHANGED
@@ -51,6 +51,8 @@ module Sidekiq
|
|
51
51
|
# at - timestamp to schedule the job (optional), must be Numeric (e.g. Time.now.to_f)
|
52
52
|
# retry - whether to retry this job if it fails, default true or an integer number of retries
|
53
53
|
# backtrace - whether to save any error backtrace, default false
|
54
|
+
#
|
55
|
+
# Any options valid for a worker class's sidekiq_options are also available here.
|
54
56
|
#
|
55
57
|
# All options must be strings, not symbols. NB: because we are serializing to JSON, all
|
56
58
|
# symbols in 'args' will be converted to strings. Note that +backtrace: true+ can take quite a bit of
|
data/lib/sidekiq/core_ext.rb
CHANGED
@@ -1,119 +1 @@
|
|
1
|
-
|
2
|
-
begin
|
3
|
-
require 'active_support/core_ext/class/attribute'
|
4
|
-
rescue LoadError
|
5
|
-
|
6
|
-
# A dumbed down version of ActiveSupport's
|
7
|
-
# Class#class_attribute helper.
|
8
|
-
class Class
|
9
|
-
def class_attribute(*attrs)
|
10
|
-
instance_writer = true
|
11
|
-
|
12
|
-
attrs.each do |name|
|
13
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
14
|
-
def self.#{name}() nil end
|
15
|
-
def self.#{name}?() !!#{name} end
|
16
|
-
|
17
|
-
def self.#{name}=(val)
|
18
|
-
singleton_class.class_eval do
|
19
|
-
define_method(:#{name}) { val }
|
20
|
-
end
|
21
|
-
|
22
|
-
if singleton_class?
|
23
|
-
class_eval do
|
24
|
-
def #{name}
|
25
|
-
defined?(@#{name}) ? @#{name} : singleton_class.#{name}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
val
|
30
|
-
end
|
31
|
-
|
32
|
-
def #{name}
|
33
|
-
defined?(@#{name}) ? @#{name} : self.class.#{name}
|
34
|
-
end
|
35
|
-
|
36
|
-
def #{name}?
|
37
|
-
!!#{name}
|
38
|
-
end
|
39
|
-
RUBY
|
40
|
-
|
41
|
-
attr_writer name if instance_writer
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
def singleton_class?
|
47
|
-
ancestors.first != self
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
begin
|
53
|
-
require 'active_support/core_ext/hash/keys'
|
54
|
-
require 'active_support/core_ext/hash/deep_merge'
|
55
|
-
rescue LoadError
|
56
|
-
class Hash
|
57
|
-
def stringify_keys
|
58
|
-
keys.each do |key|
|
59
|
-
self[key.to_s] = delete(key)
|
60
|
-
end
|
61
|
-
self
|
62
|
-
end if !{}.respond_to?(:stringify_keys)
|
63
|
-
|
64
|
-
def symbolize_keys
|
65
|
-
keys.each do |key|
|
66
|
-
self[(key.to_sym rescue key) || key] = delete(key)
|
67
|
-
end
|
68
|
-
self
|
69
|
-
end if !{}.respond_to?(:symbolize_keys)
|
70
|
-
|
71
|
-
def deep_merge(other_hash, &block)
|
72
|
-
dup.deep_merge!(other_hash, &block)
|
73
|
-
end if !{}.respond_to?(:deep_merge)
|
74
|
-
|
75
|
-
def deep_merge!(other_hash, &block)
|
76
|
-
other_hash.each_pair do |k,v|
|
77
|
-
tv = self[k]
|
78
|
-
if tv.is_a?(Hash) && v.is_a?(Hash)
|
79
|
-
self[k] = tv.deep_merge(v, &block)
|
80
|
-
else
|
81
|
-
self[k] = block && tv ? block.call(k, tv, v) : v
|
82
|
-
end
|
83
|
-
end
|
84
|
-
self
|
85
|
-
end if !{}.respond_to?(:deep_merge!)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
begin
|
90
|
-
require 'active_support/core_ext/string/inflections'
|
91
|
-
rescue LoadError
|
92
|
-
class String
|
93
|
-
def constantize
|
94
|
-
names = self.split('::')
|
95
|
-
names.shift if names.empty? || names.first.empty?
|
96
|
-
|
97
|
-
constant = Object
|
98
|
-
names.each do |name|
|
99
|
-
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
100
|
-
end
|
101
|
-
constant
|
102
|
-
end
|
103
|
-
end if !"".respond_to?(:constantize)
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
begin
|
108
|
-
require 'active_support/core_ext/kernel/reporting'
|
109
|
-
rescue LoadError
|
110
|
-
module Kernel
|
111
|
-
module_function
|
112
|
-
def silence_warnings
|
113
|
-
old_verbose, $VERBOSE = $VERBOSE, nil
|
114
|
-
yield
|
115
|
-
ensure
|
116
|
-
$VERBOSE = old_verbose
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
1
|
+
raise "no longer used, will be removed in 5.1"
|
data/lib/sidekiq/job_logger.rb
CHANGED
@@ -2,15 +2,13 @@ module Sidekiq
|
|
2
2
|
class JobLogger
|
3
3
|
|
4
4
|
def call(item, queue)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
raise
|
13
|
-
end
|
5
|
+
start = Time.now
|
6
|
+
logger.info("start".freeze)
|
7
|
+
yield
|
8
|
+
logger.info("done: #{elapsed(start)} sec")
|
9
|
+
rescue Exception
|
10
|
+
logger.info("fail: #{elapsed(start)} sec")
|
11
|
+
raise
|
14
12
|
end
|
15
13
|
|
16
14
|
private
|
@@ -24,4 +22,3 @@ module Sidekiq
|
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
27
|
-
|
data/lib/sidekiq/job_retry.rb
CHANGED
@@ -203,7 +203,7 @@ module Sidekiq
|
|
203
203
|
end
|
204
204
|
|
205
205
|
def delay_for(worker, count, exception)
|
206
|
-
worker && worker.sidekiq_retry_in_block
|
206
|
+
worker && worker.sidekiq_retry_in_block && retry_in(worker, count, exception) || seconds_to_delay(count)
|
207
207
|
end
|
208
208
|
|
209
209
|
# delayed_job uses the same basic formula
|
data/lib/sidekiq/logging.rb
CHANGED
@@ -26,6 +26,18 @@ module Sidekiq
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def self.job_hash_context(job_hash)
|
30
|
+
# If we're using a wrapper class, like ActiveJob, use the "wrapped"
|
31
|
+
# attribute to expose the underlying thing.
|
32
|
+
klass = job_hash['wrapped'.freeze] || job_hash["class".freeze]
|
33
|
+
bid = job_hash['bid'.freeze]
|
34
|
+
"#{klass} JID-#{job_hash['jid'.freeze]}#{" BID-#{bid}" if bid}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.with_job_hash_context(job_hash, &block)
|
38
|
+
with_context(job_hash_context(job_hash), &block)
|
39
|
+
end
|
40
|
+
|
29
41
|
def self.with_context(msg)
|
30
42
|
Thread.current[:sidekiq_context] ||= []
|
31
43
|
Thread.current[:sidekiq_context] << msg
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -125,12 +125,7 @@ module Sidekiq
|
|
125
125
|
# job structure to the Web UI
|
126
126
|
pristine = cloned(job_hash)
|
127
127
|
|
128
|
-
|
129
|
-
# attribute to expose the underlying thing.
|
130
|
-
klass = job_hash['wrapped'.freeze] || job_hash["class".freeze]
|
131
|
-
ctx = "#{klass} JID-#{job_hash['jid'.freeze]}#{" BID-#{job_hash['bid'.freeze]}" if job_hash['bid'.freeze]}"
|
132
|
-
|
133
|
-
Sidekiq::Logging.with_context(ctx) do
|
128
|
+
Sidekiq::Logging.with_job_hash_context(job_hash) do
|
134
129
|
@retrier.global(job_hash, queue) do
|
135
130
|
@logging.call(job_hash, queue) do
|
136
131
|
stats(pristine, queue) do
|
@@ -139,7 +134,7 @@ module Sidekiq
|
|
139
134
|
# the Reloader. It handles code loading, db connection management, etc.
|
140
135
|
# Effectively this block denotes a "unit of work" to Rails.
|
141
136
|
@reloader.call do
|
142
|
-
klass = job_hash['class'.freeze]
|
137
|
+
klass = constantize(job_hash['class'.freeze])
|
143
138
|
worker = klass.new
|
144
139
|
worker.jid = job_hash['jid'.freeze]
|
145
140
|
@retrier.local(worker, job_hash, queue) do
|
@@ -234,5 +229,14 @@ module Sidekiq
|
|
234
229
|
Marshal.load(Marshal.dump(thing))
|
235
230
|
end
|
236
231
|
|
232
|
+
def constantize(str)
|
233
|
+
names = str.split('::')
|
234
|
+
names.shift if names.empty? || names.first.empty?
|
235
|
+
|
236
|
+
names.inject(Object) do |constant, name|
|
237
|
+
constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
237
241
|
end
|
238
242
|
end
|
data/lib/sidekiq/rails.rb
CHANGED
@@ -28,7 +28,6 @@ module Sidekiq
|
|
28
28
|
Sidekiq.configure_server do |_|
|
29
29
|
if ::Rails::VERSION::MAJOR >= 5
|
30
30
|
Sidekiq.options[:reloader] = Sidekiq::Rails::Reloader.new
|
31
|
-
Psych::Visitors::ToRuby.prepend(Sidekiq::Rails::PsychAutoload)
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
@@ -48,13 +47,5 @@ module Sidekiq
|
|
48
47
|
"#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
|
49
48
|
end
|
50
49
|
end
|
51
|
-
|
52
|
-
module PsychAutoload
|
53
|
-
def resolve_class(klass_name)
|
54
|
-
klass_name && klass_name.constantize
|
55
|
-
rescue NameError
|
56
|
-
super
|
57
|
-
end
|
58
|
-
end
|
59
50
|
end if defined?(::Rails)
|
60
51
|
end
|
data/lib/sidekiq/testing.rb
CHANGED
@@ -55,6 +55,15 @@ module Sidekiq
|
|
55
55
|
yield @server_chain if block_given?
|
56
56
|
@server_chain
|
57
57
|
end
|
58
|
+
|
59
|
+
def constantize(str)
|
60
|
+
names = str.split('::')
|
61
|
+
names.shift if names.empty? || names.first.empty?
|
62
|
+
|
63
|
+
names.inject(Object) do |constant, name|
|
64
|
+
constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
65
|
+
end
|
66
|
+
end
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
@@ -76,7 +85,7 @@ module Sidekiq
|
|
76
85
|
true
|
77
86
|
elsif Sidekiq::Testing.inline?
|
78
87
|
payloads.each do |job|
|
79
|
-
klass = job['class']
|
88
|
+
klass = Sidekiq::Testing.constantize(job['class'])
|
80
89
|
job['id'] ||= SecureRandom.hex(12)
|
81
90
|
job_hash = Sidekiq.load_json(Sidekiq.dump_json(job))
|
82
91
|
klass.process_job(job_hash)
|
@@ -309,7 +318,7 @@ module Sidekiq
|
|
309
318
|
worker_classes = jobs.map { |job| job["class"] }.uniq
|
310
319
|
|
311
320
|
worker_classes.each do |worker_class|
|
312
|
-
|
321
|
+
Sidekiq::Testing.constantize(worker_class).drain
|
313
322
|
end
|
314
323
|
end
|
315
324
|
end
|
data/lib/sidekiq/util.rb
CHANGED
data/lib/sidekiq/version.rb
CHANGED
@@ -234,7 +234,6 @@ module Sidekiq
|
|
234
234
|
get '/stats' do
|
235
235
|
sidekiq_stats = Sidekiq::Stats.new
|
236
236
|
redis_stats = redis_info.select { |k, v| REDIS_KEYS.include? k }
|
237
|
-
|
238
237
|
json(
|
239
238
|
sidekiq: {
|
240
239
|
processed: sidekiq_stats.processed,
|
@@ -247,7 +246,8 @@ module Sidekiq
|
|
247
246
|
dead: sidekiq_stats.dead_size,
|
248
247
|
default_latency: sidekiq_stats.default_queue_latency
|
249
248
|
},
|
250
|
-
redis: redis_stats
|
249
|
+
redis: redis_stats,
|
250
|
+
server_utc_time: server_utc_time
|
251
251
|
)
|
252
252
|
end
|
253
253
|
|
data/lib/sidekiq/web/helpers.rb
CHANGED
@@ -15,7 +15,7 @@ module Sidekiq
|
|
15
15
|
settings.locales.each_with_object({}) do |path, global|
|
16
16
|
find_locale_files(lang).each do |file|
|
17
17
|
strs = YAML.load(File.open(file))
|
18
|
-
global.
|
18
|
+
global.merge!(strs[lang])
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -24,6 +24,7 @@ module Sidekiq
|
|
24
24
|
def clear_caches
|
25
25
|
@@strings = nil
|
26
26
|
@@locale_files = nil
|
27
|
+
@@available_locales = nil
|
27
28
|
end
|
28
29
|
|
29
30
|
def locale_files
|
@@ -32,6 +33,10 @@ module Sidekiq
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
36
|
+
def available_locales
|
37
|
+
@@available_locales ||= locale_files.map { |path| File.basename(path, '.yml') }.uniq
|
38
|
+
end
|
39
|
+
|
35
40
|
def find_locale_files(lang)
|
36
41
|
locale_files.select { |file| file =~ /\/#{lang}\.yml$/ }
|
37
42
|
end
|
@@ -73,20 +78,36 @@ module Sidekiq
|
|
73
78
|
text_direction == 'rtl'
|
74
79
|
end
|
75
80
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
81
|
+
# See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
82
|
+
def user_preferred_languages
|
83
|
+
languages = env['HTTP_ACCEPT_LANGUAGE'.freeze]
|
84
|
+
languages.to_s.downcase.gsub(/\s+/, '').split(',').map do |language|
|
85
|
+
locale, quality = language.split(';q=', 2)
|
86
|
+
locale = nil if locale == '*' # Ignore wildcards
|
87
|
+
quality = quality ? quality.to_f : 1.0
|
88
|
+
[locale, quality]
|
89
|
+
end.sort do |(_, left), (_, right)|
|
90
|
+
right <=> left
|
91
|
+
end.map(&:first).compact
|
92
|
+
end
|
93
|
+
|
94
|
+
# Given an Accept-Language header like "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2"
|
95
|
+
# this method will try to best match the available locales to the user's preferred languages.
|
96
|
+
#
|
97
|
+
# Inspiration taken from https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/parser.rb
|
80
98
|
def locale
|
81
99
|
@locale ||= begin
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
100
|
+
matched_locale = user_preferred_languages.map do |preferred|
|
101
|
+
preferred_language = preferred.split('-', 2).first
|
102
|
+
|
103
|
+
lang_group = available_locales.select do |available|
|
104
|
+
preferred_language == available.split('-', 2).first
|
105
|
+
end
|
106
|
+
|
107
|
+
lang_group.find { |lang| lang == preferred } || lang_group.min_by(&:length)
|
108
|
+
end.compact.first
|
109
|
+
|
110
|
+
matched_locale || 'en'
|
90
111
|
end
|
91
112
|
end
|
92
113
|
|
@@ -168,7 +189,11 @@ module Sidekiq
|
|
168
189
|
|
169
190
|
# Merge options with current params, filter safe params, and stringify to query string
|
170
191
|
def qparams(options)
|
171
|
-
|
192
|
+
# stringify
|
193
|
+
options.keys.each do |key|
|
194
|
+
options[key.to_s] = options.delete(key)
|
195
|
+
end
|
196
|
+
|
172
197
|
params.merge(options).map do |key, value|
|
173
198
|
SAFE_QPARAMS.include?(key) ? "#{key}=#{CGI.escape(value.to_s)}" : next
|
174
199
|
end.compact.join("&")
|
@@ -258,6 +283,10 @@ module Sidekiq
|
|
258
283
|
"Sidekiq v#{Sidekiq::VERSION}"
|
259
284
|
end
|
260
285
|
|
286
|
+
def server_utc_time
|
287
|
+
Time.now.utc.strftime('%H:%M:%S UTC')
|
288
|
+
end
|
289
|
+
|
261
290
|
def redis_connection_and_namespace
|
262
291
|
@redis_connection_and_namespace ||= begin
|
263
292
|
namespace_suffix = namespace == nil ? '' : "##{namespace}"
|
data/lib/sidekiq/worker.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'sidekiq/client'
|
3
|
-
require 'sidekiq/core_ext'
|
4
3
|
|
5
4
|
module Sidekiq
|
6
5
|
|
7
|
-
|
8
6
|
##
|
9
7
|
# Include this module in your worker class and you can easily create
|
10
8
|
# asynchronous jobs:
|
@@ -118,7 +116,8 @@ module Sidekiq
|
|
118
116
|
# In practice, any option is allowed. This is the main mechanism to configure the
|
119
117
|
# options for a specific job.
|
120
118
|
def sidekiq_options(opts={})
|
121
|
-
|
119
|
+
# stringify
|
120
|
+
self.sidekiq_options_hash = get_sidekiq_options.merge(Hash[opts.map{|k, v| [k.to_s, v]}])
|
122
121
|
end
|
123
122
|
|
124
123
|
def sidekiq_retry_in(&block)
|
@@ -135,8 +134,68 @@ module Sidekiq
|
|
135
134
|
|
136
135
|
def client_push(item) # :nodoc:
|
137
136
|
pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options['pool'.freeze] || Sidekiq.redis_pool
|
138
|
-
|
139
|
-
|
137
|
+
# stringify
|
138
|
+
item.keys.each do |key|
|
139
|
+
item[key.to_s] = item.delete(key)
|
140
|
+
end
|
141
|
+
|
142
|
+
Sidekiq::Client.new(pool).push(item)
|
143
|
+
end
|
144
|
+
|
145
|
+
def class_attribute(*attrs)
|
146
|
+
instance_reader = true
|
147
|
+
instance_writer = true
|
148
|
+
|
149
|
+
attrs.each do |name|
|
150
|
+
singleton_class.instance_eval do
|
151
|
+
undef_method(name) if method_defined?(name) || private_method_defined?(name)
|
152
|
+
end
|
153
|
+
define_singleton_method(name) { nil }
|
154
|
+
|
155
|
+
ivar = "@#{name}"
|
156
|
+
|
157
|
+
singleton_class.instance_eval do
|
158
|
+
m = "#{name}="
|
159
|
+
undef_method(m) if method_defined?(m) || private_method_defined?(m)
|
160
|
+
end
|
161
|
+
define_singleton_method("#{name}=") do |val|
|
162
|
+
singleton_class.class_eval do
|
163
|
+
undef_method(name) if method_defined?(name) || private_method_defined?(name)
|
164
|
+
define_method(name) { val }
|
165
|
+
end
|
166
|
+
|
167
|
+
if singleton_class?
|
168
|
+
class_eval do
|
169
|
+
undef_method(name) if method_defined?(name) || private_method_defined?(name)
|
170
|
+
define_method(name) do
|
171
|
+
if instance_variable_defined? ivar
|
172
|
+
instance_variable_get ivar
|
173
|
+
else
|
174
|
+
singleton_class.send name
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
val
|
180
|
+
end
|
181
|
+
|
182
|
+
if instance_reader
|
183
|
+
undef_method(name) if method_defined?(name) || private_method_defined?(name)
|
184
|
+
define_method(name) do
|
185
|
+
if instance_variable_defined?(ivar)
|
186
|
+
instance_variable_get ivar
|
187
|
+
else
|
188
|
+
self.class.public_send name
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if instance_writer
|
194
|
+
m = "#{name}="
|
195
|
+
undef_method(m) if method_defined?(m) || private_method_defined?(m)
|
196
|
+
attr_writer name
|
197
|
+
end
|
198
|
+
end
|
140
199
|
end
|
141
200
|
|
142
201
|
end
|
@@ -111,8 +111,11 @@ var realtimeGraph = function(updatePath) {
|
|
111
111
|
|
112
112
|
updateStatsSummary(data.sidekiq);
|
113
113
|
updateRedisStats(data.redis);
|
114
|
+
updateFooterUTCTime(data.server_utc_time)
|
115
|
+
|
114
116
|
pulseBeacon();
|
115
117
|
});
|
118
|
+
|
116
119
|
i++;
|
117
120
|
}, timeInterval);
|
118
121
|
}
|
@@ -224,6 +227,10 @@ var updateRedisStats = function(data) {
|
|
224
227
|
$('.stat h3.used_memory_peak_human').html(data.used_memory_peak_human)
|
225
228
|
}
|
226
229
|
|
230
|
+
var updateFooterUTCTime = function(time) {
|
231
|
+
$('.navbar-fixed-bottom .navbar-inner .server-utc-time').html(time)
|
232
|
+
}
|
233
|
+
|
227
234
|
var pulseBeacon = function(){
|
228
235
|
$('.beacon').addClass('pulse').delay(1000).queue(function(){
|
229
236
|
$(this).removeClass('pulse').dequeue();
|
data/web/views/_footer.erb
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
<p class="navbar-text redis-url" title="<%= redis_connection_and_namespace %>"><%= redis_connection_and_namespace %></p>
|
10
10
|
</li>
|
11
11
|
<li>
|
12
|
-
<p class="navbar-text"><%=
|
12
|
+
<p class="navbar-text server-utc-time"><%= server_utc_time %></p>
|
13
13
|
</li>
|
14
14
|
</ul>
|
15
15
|
</div>
|
data/web/views/busy.erb
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
<th><%= t('Busy') %></th>
|
23
23
|
<th> </th>
|
24
24
|
</thead>
|
25
|
+
<% lead = processes.leader %>
|
25
26
|
<% processes.each do |process| %>
|
26
27
|
<tr>
|
27
28
|
<td class="box">
|
@@ -31,7 +32,10 @@
|
|
31
32
|
<span class="label label-info"><%= label %></span>
|
32
33
|
<% end %>
|
33
34
|
<% if process.stopping? %>
|
34
|
-
<span class="label label-danger">
|
35
|
+
<span class="label label-danger">quiet</span>
|
36
|
+
<% end %>
|
37
|
+
<% if process.identity == lead %>
|
38
|
+
<span class="label label-warning">leader</span>
|
35
39
|
<% end %>
|
36
40
|
<br>
|
37
41
|
<b><%= "#{t('Queues')}: " %></b>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|