sidekiq-grouping 1.0.10 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/lint.yml +37 -0
- data/.github/workflows/test.yml +49 -0
- data/.rubocop.yml +31 -3
- data/Appraisals +6 -2
- data/README.md +3 -1
- data/gemfiles/sidekiq_6.0.gemfile +7 -0
- data/gemfiles/sidekiq_6.5.gemfile +7 -0
- data/lefthook.yml +15 -0
- data/lib/sidekiq/grouping/batch.rb +29 -19
- data/lib/sidekiq/grouping/config.rb +32 -22
- data/lib/sidekiq/grouping/flusher.rb +48 -36
- data/lib/sidekiq/grouping/flusher_observer.rb +16 -10
- data/lib/sidekiq/grouping/middleware.rb +27 -14
- data/lib/sidekiq/grouping/redis.rb +23 -14
- data/lib/sidekiq/grouping/version.rb +3 -1
- data/lib/sidekiq/grouping/web.rb +10 -5
- data/lib/sidekiq/grouping.rb +36 -30
- data/sidekiq-grouping.gemspec +14 -8
- data/spec/modules/batch_spec.rb +110 -80
- data/spec/modules/redis_spec.rb +17 -16
- data/spec/spec_helper.rb +5 -3
- data/spec/support/test_workers.rb +7 -10
- metadata +61 -27
- data/.travis.yml +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be68edcca66201c059ee0a9d18c163cf899a00e1d5013a64ca72206dc9b48e9e
|
4
|
+
data.tar.gz: 55bfb74ecd86ce73a4fedd115e8adfb1a8531ab3460e008a74ce6c4b9c111892
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 709bbcf1bf236c18e330adba5fd5c0c23a5cce73f869fcc152c3b846f306c28189c3942bb6bfde1875f1895e0a799e7367e1e4bddd4abb8c6147f16490101841
|
7
|
+
data.tar.gz: d46cb5d01ccaaae7c52f7768e8f8159a8be287e58852f6c167d4ebfbf01e37da70640b40b4476c868fa01a4874d717bbb4c0cbe9108418d1180c4a2c9d95c3ce
|
@@ -0,0 +1,37 @@
|
|
1
|
+
---
|
2
|
+
name: Lint
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- master
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
rubocop:
|
13
|
+
name: Rubocop
|
14
|
+
runs-on: ubuntu-latest
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v3
|
17
|
+
|
18
|
+
- name: Set up Ruby ${{ matrix.ruby_version }}
|
19
|
+
uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
bundler: 2
|
22
|
+
ruby-version: 2.7
|
23
|
+
|
24
|
+
- uses: actions/cache@v3
|
25
|
+
with:
|
26
|
+
path: vendor/bundle
|
27
|
+
key: ${{ runner.os }}-gems-${{ matrix.ruby-version }}-${{ hashFiles('./*.gemspec') }}
|
28
|
+
restore-keys: |
|
29
|
+
${{ runner.os }}-gems-
|
30
|
+
|
31
|
+
- name: Bundle install
|
32
|
+
run: |
|
33
|
+
bundle config path vendor/bundle
|
34
|
+
bundle install --jobs 4 --retry 3
|
35
|
+
|
36
|
+
- name: Run Rubocop
|
37
|
+
run: bundle exec rubocop
|
@@ -0,0 +1,49 @@
|
|
1
|
+
---
|
2
|
+
name: Test
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- master
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
rspec:
|
13
|
+
name: Rspec
|
14
|
+
runs-on: ubuntu-latest
|
15
|
+
services:
|
16
|
+
redis:
|
17
|
+
image: redis:6
|
18
|
+
options: >-
|
19
|
+
--health-cmd "redis-cli ping"
|
20
|
+
--health-interval 10s
|
21
|
+
--health-timeout 5s
|
22
|
+
--health-retries 5
|
23
|
+
ports:
|
24
|
+
- 6379:6379
|
25
|
+
strategy:
|
26
|
+
matrix:
|
27
|
+
include:
|
28
|
+
- { ruby_version: 2.7 }
|
29
|
+
- { ruby_version: 3.0 }
|
30
|
+
- { ruby_version: 3.1 }
|
31
|
+
steps:
|
32
|
+
- uses: actions/checkout@v3
|
33
|
+
|
34
|
+
- name: Set up Ruby ${{ matrix.ruby_version }}
|
35
|
+
uses: ruby/setup-ruby@v1
|
36
|
+
with:
|
37
|
+
bundler: 2
|
38
|
+
ruby-version: ${{ matrix.ruby_version }}
|
39
|
+
|
40
|
+
# Appraisal doesn't support vendored install
|
41
|
+
# See: https://github.com/thoughtbot/appraisal/issues/173
|
42
|
+
# https://github.com/thoughtbot/appraisal/pull/174
|
43
|
+
- name: Bundle install
|
44
|
+
run: |
|
45
|
+
bundle install --jobs 4 --retry 3
|
46
|
+
bundle exec appraisal install
|
47
|
+
|
48
|
+
- name: Run tests
|
49
|
+
run: bundle exec appraisal rspec
|
data/.rubocop.yml
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
---
|
1
2
|
require: rubocop-rspec
|
2
3
|
|
3
4
|
AllCops:
|
5
|
+
TargetRubyVersion: 2.7.0
|
6
|
+
SuggestExtensions: false
|
7
|
+
NewCops: enable
|
4
8
|
Include:
|
5
9
|
- ./Gemfile
|
10
|
+
- ./Rakefile
|
11
|
+
- '*.gemspec'
|
12
|
+
- '**/*.rb'
|
6
13
|
|
7
14
|
Documentation:
|
8
15
|
Enabled: false
|
@@ -10,8 +17,29 @@ Documentation:
|
|
10
17
|
Style/StringLiterals:
|
11
18
|
EnforcedStyle: double_quotes
|
12
19
|
|
13
|
-
Style/ClassAndModuleChildren:
|
14
|
-
EnforcedStyle: compact
|
15
|
-
|
16
20
|
RSpec/FilePath:
|
17
21
|
Enabled: false
|
22
|
+
|
23
|
+
RSpec/ExampleLength:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
RSpec/AnyInstance:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Metrics/MethodLength:
|
30
|
+
Max: 15
|
31
|
+
|
32
|
+
Metrics/ClassLength:
|
33
|
+
Max: 150
|
34
|
+
|
35
|
+
Layout/LineLength:
|
36
|
+
Max: 80
|
37
|
+
|
38
|
+
Layout/FirstArgumentIndentation:
|
39
|
+
EnforcedStyle: consistent
|
40
|
+
|
41
|
+
Layout/FirstMethodArgumentLineBreak:
|
42
|
+
Enabled: true
|
43
|
+
|
44
|
+
Layout/MultilineMethodArgumentLineBreaks:
|
45
|
+
Enabled: true
|
data/Appraisals
CHANGED
@@ -14,6 +14,10 @@ appraise 'sidekiq-5.0' do
|
|
14
14
|
gem 'sidekiq', '~> 5.0.0'
|
15
15
|
end
|
16
16
|
|
17
|
-
appraise 'sidekiq-
|
18
|
-
gem 'sidekiq',
|
17
|
+
appraise 'sidekiq-6.0' do
|
18
|
+
gem 'sidekiq', '~> 6.0.0'
|
19
|
+
end
|
20
|
+
|
21
|
+
appraise 'sidekiq-6.5' do
|
22
|
+
gem 'sidekiq', '~> 6.5.0'
|
19
23
|
end
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://rubygems.org/gems/sidekiq-grouping)
|
2
|
+
|
1
3
|
# Sidekiq::Grouping
|
2
4
|
|
3
5
|
<a href="https://evilmartians.com/?utm_source=sidekiq-grouping-gem">
|
@@ -23,7 +25,7 @@ class ElasticBulkIndexWorker
|
|
23
25
|
include Sidekiq::Worker
|
24
26
|
|
25
27
|
sidekiq_options(
|
26
|
-
queue: :
|
28
|
+
queue: :elastic_bulks,
|
27
29
|
batch_flush_size: 30, # Jobs will be combined when queue size exceeds 30
|
28
30
|
batch_flush_interval: 60, # Jobs will be combined every 60 seconds
|
29
31
|
retry: 5
|
data/lefthook.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
# Git hooks configuration
|
3
|
+
#
|
4
|
+
# See: github.com/evilmartians/lefthook
|
5
|
+
|
6
|
+
pre-commit:
|
7
|
+
commands:
|
8
|
+
rubocop:
|
9
|
+
glob: "*.rb"
|
10
|
+
run: bundle exec rubocop -A {staged_files} && git add {staged_files}
|
11
|
+
|
12
|
+
pre-push:
|
13
|
+
commands:
|
14
|
+
rspec:
|
15
|
+
run: bundle exec appraisal rspec
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sidekiq
|
2
4
|
module Grouping
|
3
5
|
class Batch
|
4
|
-
def initialize(worker_class, queue,
|
6
|
+
def initialize(worker_class, queue, _redis_pool = nil)
|
5
7
|
@worker_class = worker_class
|
6
8
|
@queue = queue
|
7
9
|
@name = "#{worker_class.underscore}:#{queue}"
|
@@ -12,11 +14,18 @@ module Sidekiq
|
|
12
14
|
|
13
15
|
def add(msg)
|
14
16
|
msg = msg.to_json
|
15
|
-
|
17
|
+
return unless should_add? msg
|
18
|
+
|
19
|
+
@redis.push_msg(
|
20
|
+
@name,
|
21
|
+
msg,
|
22
|
+
remember_unique: enqueue_similar_once?
|
23
|
+
)
|
16
24
|
end
|
17
25
|
|
18
|
-
def should_add?
|
26
|
+
def should_add?(msg)
|
19
27
|
return true unless enqueue_similar_once?
|
28
|
+
|
20
29
|
!@redis.enqueued?(@name, msg)
|
21
30
|
end
|
22
31
|
|
@@ -25,19 +34,19 @@ module Sidekiq
|
|
25
34
|
end
|
26
35
|
|
27
36
|
def chunk_size
|
28
|
-
worker_class_options[
|
37
|
+
worker_class_options["batch_size"] ||
|
29
38
|
Sidekiq::Grouping::Config.max_batch_size
|
30
39
|
end
|
31
40
|
|
32
41
|
def pluck_size
|
33
|
-
worker_class_options[
|
42
|
+
worker_class_options["batch_flush_size"] ||
|
34
43
|
chunk_size
|
35
44
|
end
|
36
45
|
|
37
46
|
def pluck
|
38
|
-
|
39
|
-
|
40
|
-
|
47
|
+
return unless @redis.lock(@name)
|
48
|
+
|
49
|
+
@redis.pluck(@name, pluck_size).map { |value| JSON.parse(value) }
|
41
50
|
end
|
42
51
|
|
43
52
|
def flush
|
@@ -46,9 +55,9 @@ module Sidekiq
|
|
46
55
|
|
47
56
|
chunk.each_slice(chunk_size) do |subchunk|
|
48
57
|
Sidekiq::Client.push(
|
49
|
-
|
50
|
-
|
51
|
-
|
58
|
+
"class" => @worker_class,
|
59
|
+
"queue" => @queue,
|
60
|
+
"args" => [true, subchunk]
|
52
61
|
)
|
53
62
|
end
|
54
63
|
set_current_time_as_last
|
@@ -74,10 +83,11 @@ module Sidekiq
|
|
74
83
|
end
|
75
84
|
|
76
85
|
def next_execution_time
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
86
|
+
interval = worker_class_options["batch_flush_interval"]
|
87
|
+
return unless interval
|
88
|
+
|
89
|
+
last_time = last_execution_time
|
90
|
+
last_time + interval.seconds if last_time
|
81
91
|
end
|
82
92
|
|
83
93
|
def delete
|
@@ -99,13 +109,13 @@ module Sidekiq
|
|
99
109
|
if last_time.blank?
|
100
110
|
set_current_time_as_last
|
101
111
|
false
|
102
|
-
|
103
|
-
next_time < Time.now
|
112
|
+
elsif next_time
|
113
|
+
next_time < Time.now
|
104
114
|
end
|
105
115
|
end
|
106
116
|
|
107
117
|
def enqueue_similar_once?
|
108
|
-
worker_class_options[
|
118
|
+
worker_class_options["batch_unique"] == true
|
109
119
|
end
|
110
120
|
|
111
121
|
def set_current_time_as_last
|
@@ -122,7 +132,7 @@ module Sidekiq
|
|
122
132
|
end
|
123
133
|
|
124
134
|
def extract_worker_klass_and_queue(name)
|
125
|
-
klass, queue = name.split(
|
135
|
+
klass, queue = name.split(":")
|
126
136
|
[klass.camelize, queue]
|
127
137
|
end
|
128
138
|
end
|
@@ -1,29 +1,39 @@
|
|
1
|
-
|
2
|
-
include ActiveSupport::Configurable
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Sidekiq
|
4
|
+
module Grouping
|
5
|
+
module Config
|
6
|
+
include ActiveSupport::Configurable
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def self.options
|
9
|
+
if Sidekiq.respond_to?(:[])
|
10
|
+
Sidekiq[:grouping] || Sidekiq["grouping"] || {}
|
11
|
+
else
|
12
|
+
Sidekiq.options[:grouping] || Sidekiq.options["grouping"] || {}
|
13
|
+
end
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
# Queue size overflow check polling interval
|
17
|
+
config_accessor :poll_interval do
|
18
|
+
options[:poll_interval] || 3
|
19
|
+
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
# Maximum batch size
|
22
|
+
config_accessor :max_batch_size do
|
23
|
+
options[:max_batch_size] || 1000
|
24
|
+
end
|
25
|
+
|
26
|
+
# Batch queue flush lock timeout
|
27
|
+
config_accessor :lock_ttl do
|
28
|
+
options[:lock_ttl] || 1
|
29
|
+
end
|
22
30
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
31
|
+
# Option to override how Sidekiq::Grouping know about tests env
|
32
|
+
config_accessor :tests_env do
|
33
|
+
options[:tests_env] || (
|
34
|
+
defined?(::Rails) && Rails.respond_to?(:env) && Rails.env.test?
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
28
38
|
end
|
29
39
|
end
|
@@ -1,42 +1,54 @@
|
|
1
|
-
|
2
|
-
def flush
|
3
|
-
batches = Sidekiq::Grouping::Batch.all.map do |batch|
|
4
|
-
batch if batch.could_flush?
|
5
|
-
end
|
6
|
-
flush_batches(batches)
|
7
|
-
end
|
1
|
+
# frozen_string_literal: true
|
8
2
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
"change 'tests_env' to cover this one"
|
19
|
-
].join)
|
20
|
-
Sidekiq::Grouping.logger.warn(
|
21
|
-
"**************************************************"
|
22
|
-
)
|
23
|
-
end
|
24
|
-
flush_batches(Sidekiq::Grouping::Batch.all)
|
25
|
-
end
|
3
|
+
module Sidekiq
|
4
|
+
module Grouping
|
5
|
+
class Flusher
|
6
|
+
def flush
|
7
|
+
batches = Sidekiq::Grouping::Batch.all.map do |batch|
|
8
|
+
batch if batch.could_flush?
|
9
|
+
end
|
10
|
+
flush_batches(batches)
|
11
|
+
end
|
26
12
|
|
27
|
-
|
13
|
+
def force_flush_for_test!
|
14
|
+
unless Sidekiq::Grouping::Config.tests_env
|
15
|
+
Sidekiq::Grouping.logger.warn(
|
16
|
+
"**************************************************"
|
17
|
+
)
|
18
|
+
Sidekiq::Grouping.logger.warn(
|
19
|
+
"⛔️ force_flush_for_test! for testing API, " \
|
20
|
+
"but this is not the test environment. " \
|
21
|
+
"Please check your environment or " \
|
22
|
+
"change 'tests_env' to cover this one"
|
23
|
+
)
|
24
|
+
Sidekiq::Grouping.logger.warn(
|
25
|
+
"**************************************************"
|
26
|
+
)
|
27
|
+
end
|
28
|
+
flush_batches(Sidekiq::Grouping::Batch.all)
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
def flush_batches(batches)
|
34
|
+
batches.compact!
|
35
|
+
flush_concrete(batches)
|
36
|
+
end
|
33
37
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def flush_concrete(batches)
|
39
|
+
return if batches.empty?
|
40
|
+
|
41
|
+
names = batches.map do |batch|
|
42
|
+
"#{batch.worker_class} in #{batch.queue}"
|
43
|
+
end
|
44
|
+
unless Sidekiq::Grouping::Config.tests_env
|
45
|
+
Sidekiq::Grouping.logger.info(
|
46
|
+
"[Sidekiq::Grouping] Trying to flush batched queues: " \
|
47
|
+
"#{names.join(',')}"
|
48
|
+
)
|
49
|
+
end
|
50
|
+
batches.each(&:flush)
|
51
|
+
end
|
52
|
+
end
|
41
53
|
end
|
42
54
|
end
|
@@ -1,13 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
module Grouping
|
5
|
+
class FlusherObserver
|
6
|
+
def update(time, _result, exception)
|
7
|
+
if exception.is_a?(Concurrent::TimeoutError)
|
8
|
+
Sidekiq::Grouping.logger.error(
|
9
|
+
"[Sidekiq::Grouping] (#{time}) Execution timed out\n"
|
10
|
+
)
|
11
|
+
elsif exception.present?
|
12
|
+
Sidekiq::Grouping.logger.error(
|
13
|
+
"[Sidekiq::Grouping] Execution failed with error #{exception}\n"
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
11
17
|
end
|
12
18
|
end
|
13
19
|
end
|
@@ -1,43 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sidekiq
|
2
4
|
module Grouping
|
3
5
|
class Middleware
|
6
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
4
7
|
def call(worker_class, msg, queue, redis_pool = nil)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
+
if worker_class.is_a?(String)
|
9
|
+
worker_class = worker_class.camelize.constantize
|
10
|
+
end
|
8
11
|
options = worker_class.get_sidekiq_options
|
9
12
|
|
10
13
|
batch =
|
11
|
-
options.key?(
|
12
|
-
options.key?(
|
13
|
-
options.key?(
|
14
|
+
options.key?("batch_flush_size") ||
|
15
|
+
options.key?("batch_flush_interval") ||
|
16
|
+
options.key?("batch_size")
|
14
17
|
|
15
18
|
passthrough =
|
16
|
-
msg[
|
17
|
-
msg[
|
18
|
-
msg['args'].try(:first) == true
|
19
|
+
msg["args"].is_a?(Array) &&
|
20
|
+
msg["args"].try(:first) == true
|
19
21
|
|
20
22
|
retrying = msg["failed_at"].present?
|
21
23
|
|
22
24
|
return yield unless batch
|
23
25
|
|
24
|
-
if
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
if inline_mode?
|
27
|
+
wrapped_args = [[msg["args"]]]
|
28
|
+
msg["args"] = wrapped_args
|
29
|
+
return yield
|
30
|
+
end
|
31
|
+
|
32
|
+
if passthrough || retrying
|
33
|
+
msg["args"].shift if passthrough
|
28
34
|
yield
|
35
|
+
else
|
36
|
+
add_to_batch(worker_class, queue, msg, redis_pool)
|
29
37
|
end
|
30
38
|
end
|
39
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
31
40
|
|
32
41
|
private
|
33
42
|
|
34
43
|
def add_to_batch(worker_class, queue, msg, redis_pool = nil)
|
35
44
|
Sidekiq::Grouping::Batch
|
36
45
|
.new(worker_class.name, queue, redis_pool)
|
37
|
-
.add(msg[
|
46
|
+
.add(msg["args"])
|
38
47
|
|
39
48
|
nil
|
40
49
|
end
|
50
|
+
|
51
|
+
def inline_mode?
|
52
|
+
defined?(Sidekiq::Testing) && Sidekiq::Testing.inline?
|
53
|
+
end
|
41
54
|
end
|
42
55
|
end
|
43
56
|
end
|
@@ -1,22 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sidekiq
|
2
4
|
module Grouping
|
3
5
|
class Redis
|
4
|
-
|
5
6
|
PLUCK_SCRIPT = <<-SCRIPT
|
6
|
-
local pluck_values = redis.call('
|
7
|
-
|
8
|
-
|
9
|
-
redis.call('srem', KEYS[2], v)
|
7
|
+
local pluck_values = redis.call('lpop', KEYS[1], ARGV[1]) or {}
|
8
|
+
if #pluck_values > 0 then
|
9
|
+
redis.call('srem', KEYS[2], unpack(pluck_values))
|
10
10
|
end
|
11
11
|
return pluck_values
|
12
12
|
SCRIPT
|
13
13
|
|
14
|
-
def push_msg(name, msg, remember_unique
|
14
|
+
def push_msg(name, msg, remember_unique: false)
|
15
15
|
redis do |conn|
|
16
|
-
conn.multi do
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
conn.multi do |pipeline|
|
17
|
+
sadd = pipeline.respond_to?(:sadd?) ? :sadd? : :sadd
|
18
|
+
pipeline.public_send(sadd, ns("batches"), name)
|
19
|
+
pipeline.rpush(ns(name), msg)
|
20
|
+
if remember_unique
|
21
|
+
pipeline.public_send(
|
22
|
+
sadd,
|
23
|
+
unique_messages_key(name),
|
24
|
+
msg
|
25
|
+
)
|
26
|
+
end
|
20
27
|
end
|
21
28
|
end
|
22
29
|
end
|
@@ -32,7 +39,7 @@ module Sidekiq
|
|
32
39
|
end
|
33
40
|
|
34
41
|
def batches
|
35
|
-
redis { |conn| conn.smembers(ns(
|
42
|
+
redis { |conn| conn.smembers(ns("batches")) }
|
36
43
|
end
|
37
44
|
|
38
45
|
def pluck(name, limit)
|
@@ -46,7 +53,9 @@ module Sidekiq
|
|
46
53
|
end
|
47
54
|
|
48
55
|
def set_last_execution_time(name, time)
|
49
|
-
redis
|
56
|
+
redis do |conn|
|
57
|
+
conn.set(ns("last_execution_time:#{name}"), time.to_json)
|
58
|
+
end
|
50
59
|
end
|
51
60
|
|
52
61
|
def lock(name)
|
@@ -60,13 +69,13 @@ module Sidekiq
|
|
60
69
|
redis do |conn|
|
61
70
|
conn.del(ns("last_execution_time:#{name}"))
|
62
71
|
conn.del(ns(name))
|
63
|
-
conn.srem(ns(
|
72
|
+
conn.srem(ns("batches"), name)
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
67
76
|
private
|
68
77
|
|
69
|
-
def unique_messages_key
|
78
|
+
def unique_messages_key(name)
|
70
79
|
ns("#{name}:unique_messages")
|
71
80
|
end
|
72
81
|
|