sidekiq-merger 0.0.4 → 0.0.5
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/README.md +9 -4
- data/lib/sidekiq/merger/merge.rb +9 -9
- data/lib/sidekiq/merger/redis.rb +10 -10
- data/lib/sidekiq/merger/version.rb +1 -1
- data/spec/sidekiq/merger/merge_spec.rb +4 -4
- data/spec/sidekiq/merger/redis_spec.rb +93 -26
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2333d3953e27f0ba0d3f0efc23a8bc48747b2a6d
|
4
|
+
data.tar.gz: ed6230c813938f38f4092ee9a27589a774c55029
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 271adc650104013b83c9fa5b99672c995c10b7e2d3518485daa9b5f2d62a9fc14333cd29014d8024f0e17a7b6bcfea393010d544f1ca899bab876a9a14647f7d
|
7
|
+
data.tar.gz: 1e647aa5449188f1649bd57a84fb34629f348996991e28085aa19a83139cd31eaa2ec089aebb82f6e6cfcd4ec57ffc0738eb52118a07498d72c851d8aeefb9a0
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
[![Coverage Status][cov-image]][cov-link]
|
7
7
|
[![Code Climate][gpa-image]][gpa-link]
|
8
8
|
|
9
|
-
Merge sidekiq jobs occurring
|
9
|
+
Merge sidekiq jobs occurring before the execution time. Inspired by [sidekiq-grouping](https://github.com/gzigzigzeo/sidekiq-grouping).
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -34,8 +34,10 @@ class SomeWorker
|
|
34
34
|
|
35
35
|
sidekiq_options merger: { key: -> (args) { args[0] } }
|
36
36
|
|
37
|
-
def perform(*
|
38
|
-
|
37
|
+
def perform(*merged_args)
|
38
|
+
merged_args.each do |args|
|
39
|
+
# Do something
|
40
|
+
end
|
39
41
|
end
|
40
42
|
end
|
41
43
|
```
|
@@ -46,9 +48,12 @@ Then, enqueue jobs by `perform_in` or `perform_at`.
|
|
46
48
|
SomeWorker.perform_in 100, 4
|
47
49
|
SomeWorker.perform_in 100, 3
|
48
50
|
SomeWorker.perform_in 100, 5
|
51
|
+
# Passed 100 seconds from the first enqueue.
|
52
|
+
SomeWorker.perform_in 100, 6
|
53
|
+
SomeWorker.perform_in 100, 1
|
49
54
|
```
|
50
55
|
|
51
|
-
`SomeWorker` will be executed in 100 seconds with args of `[4], [3], [5]`.
|
56
|
+
`SomeWorker` will be executed in 100 seconds with args of `[4], [3], [5]`, then with args of `[6], [1]`.
|
52
57
|
|
53
58
|
`perform_async` works without merging args.
|
54
59
|
|
data/lib/sidekiq/merger/merge.rb
CHANGED
@@ -6,7 +6,7 @@ class Sidekiq::Merger::Merge
|
|
6
6
|
def all
|
7
7
|
redis = Sidekiq::Merger::Redis.new
|
8
8
|
|
9
|
-
redis.
|
9
|
+
redis.all_merges.map { |full_merge_key| initialize_with_full_merge_key(full_merge_key, redis: redis) }
|
10
10
|
end
|
11
11
|
|
12
12
|
def initialize_with_full_merge_key(full_merge_key, options = {})
|
@@ -47,17 +47,17 @@ class Sidekiq::Merger::Merge
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def add(args, execution_time)
|
50
|
-
if !options[:unique] || !@redis.
|
51
|
-
@redis.
|
50
|
+
if !options[:unique] || !@redis.merge_exists?(full_merge_key, args)
|
51
|
+
@redis.push_message(full_merge_key, args, execution_time)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
55
|
def delete(args)
|
56
|
-
@redis.
|
56
|
+
@redis.delete_message(full_merge_key, args)
|
57
57
|
end
|
58
58
|
|
59
59
|
def delete_all
|
60
|
-
@redis.
|
60
|
+
@redis.delete_merge(full_merge_key)
|
61
61
|
end
|
62
62
|
|
63
63
|
def size
|
@@ -67,8 +67,8 @@ class Sidekiq::Merger::Merge
|
|
67
67
|
def flush
|
68
68
|
msgs = []
|
69
69
|
|
70
|
-
if @redis.
|
71
|
-
msgs = @redis.
|
70
|
+
if @redis.lock_merge(full_merge_key, Sidekiq::Merger::Config.lock_ttl)
|
71
|
+
msgs = @redis.pluck_merge(full_merge_key)
|
72
72
|
end
|
73
73
|
|
74
74
|
unless msgs.empty?
|
@@ -90,11 +90,11 @@ class Sidekiq::Merger::Merge
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def all_args
|
93
|
-
@redis.
|
93
|
+
@redis.get_merge(full_merge_key)
|
94
94
|
end
|
95
95
|
|
96
96
|
def execution_time
|
97
|
-
@execution_time ||= @redis.
|
97
|
+
@execution_time ||= @redis.merge_execution_time(full_merge_key)
|
98
98
|
end
|
99
99
|
|
100
100
|
def ==(other)
|
data/lib/sidekiq/merger/redis.rb
CHANGED
@@ -42,7 +42,7 @@ class Sidekiq::Merger::Redis
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
45
|
+
def push_message(key, msg, execution_time)
|
46
46
|
msg_json = msg.to_json
|
47
47
|
redis do |conn|
|
48
48
|
conn.multi do
|
@@ -54,17 +54,17 @@ class Sidekiq::Merger::Redis
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
57
|
+
def delete_message(key, msg)
|
58
58
|
msg_json = msg.to_json
|
59
59
|
redis do |conn|
|
60
60
|
conn.multi do
|
61
61
|
conn.srem(unique_msg_key(key), msg_json)
|
62
|
-
conn.lrem(msg_key(key), msg_json)
|
62
|
+
conn.lrem(msg_key(key), 0, msg_json)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
67
|
+
def merge_execution_time(key)
|
68
68
|
redis do |conn|
|
69
69
|
t = conn.get(time_key(key))
|
70
70
|
Time.at(t.to_i) unless t.nil?
|
@@ -75,26 +75,26 @@ class Sidekiq::Merger::Redis
|
|
75
75
|
redis { |conn| conn.llen(msg_key(key)) }
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
78
|
+
def merge_exists?(key, msg)
|
79
79
|
msg_json = msg.to_json
|
80
80
|
redis { |conn| conn.sismember(unique_msg_key(key), msg_json) }
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
83
|
+
def all_merges
|
84
84
|
redis { |conn| conn.smembers(merges_key) }
|
85
85
|
end
|
86
86
|
|
87
|
-
def
|
87
|
+
def lock_merge(key, ttl)
|
88
88
|
redis { |conn| conn.set(lock_key(key), true, nx: true, ex: ttl) }
|
89
89
|
end
|
90
90
|
|
91
|
-
def
|
91
|
+
def get_merge(key)
|
92
92
|
msgs = []
|
93
93
|
redis { |conn| msgs = conn.lrange(msg_key(key), 0, -1) }
|
94
94
|
msgs.map { |msg| JSON.parse(msg) }
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
97
|
+
def pluck_merge(key)
|
98
98
|
msgs = []
|
99
99
|
redis do |conn|
|
100
100
|
conn.multi do
|
@@ -108,7 +108,7 @@ class Sidekiq::Merger::Redis
|
|
108
108
|
extract_future_value(msgs).map { |msg| JSON.parse(msg) }
|
109
109
|
end
|
110
110
|
|
111
|
-
def
|
111
|
+
def delete_merge(key)
|
112
112
|
redis do |conn|
|
113
113
|
conn.multi do
|
114
114
|
conn.del(unique_msg_key(key))
|
@@ -63,19 +63,19 @@ describe Sidekiq::Merger::Merge do
|
|
63
63
|
|
64
64
|
describe "#add" do
|
65
65
|
it "adds the args in lazy merge" do
|
66
|
-
expect(redis).to receive(:
|
66
|
+
expect(redis).to receive(:push_message).with("name:queue:foo", [1, 2, 3], execution_time)
|
67
67
|
subject.add([1, 2, 3], execution_time)
|
68
68
|
end
|
69
69
|
context "with unique option" do
|
70
70
|
let(:options) { { key: -> (args) { args.to_json }, unique: true } }
|
71
71
|
it "adds the args in lazy merge" do
|
72
|
-
expect(redis).to receive(:
|
72
|
+
expect(redis).to receive(:push_message).with("name:queue:foo", [1, 2, 3], execution_time)
|
73
73
|
subject.add([1, 2, 3], execution_time)
|
74
74
|
end
|
75
75
|
context "the args has alredy been added" do
|
76
76
|
before { subject.add([1, 2, 3], execution_time) }
|
77
77
|
it "adds the args in lazy merge" do
|
78
|
-
expect(redis).not_to receive(:
|
78
|
+
expect(redis).not_to receive(:push_message)
|
79
79
|
subject.add([1, 2, 3], execution_time)
|
80
80
|
end
|
81
81
|
end
|
@@ -84,7 +84,7 @@ describe Sidekiq::Merger::Merge do
|
|
84
84
|
|
85
85
|
describe "#delete" do
|
86
86
|
it "adds the args in lazy merge" do
|
87
|
-
expect(redis).to receive(:
|
87
|
+
expect(redis).to receive(:delete_message).with("name:queue:foo", [1, 2, 3])
|
88
88
|
subject.delete([1, 2, 3])
|
89
89
|
end
|
90
90
|
end
|
@@ -26,10 +26,10 @@ describe Sidekiq::Merger::Redis do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
describe "#
|
30
|
-
shared_examples_for "
|
31
|
-
it "pushes the
|
32
|
-
subject.
|
29
|
+
describe "#push_message" do
|
30
|
+
shared_examples_for "push_message spec" do
|
31
|
+
it "pushes the msg" do
|
32
|
+
subject.push_message(pushing_key, pushing_msg, pushing_execution_time)
|
33
33
|
described_class.redis do |conn|
|
34
34
|
expect(conn.smembers("sidekiq-merger:merges")).to contain_exactly(*merge_keys)
|
35
35
|
expect(conn.keys("sidekiq-merger:time:*")).to contain_exactly(*times.keys)
|
@@ -44,7 +44,7 @@ describe Sidekiq::Merger::Redis do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
it "sets the execution time" do
|
47
|
-
subject.
|
47
|
+
subject.push_message(pushing_key, pushing_msg, pushing_execution_time)
|
48
48
|
described_class.redis do |conn|
|
49
49
|
merge_keys.each do |key, time|
|
50
50
|
expect(conn.get(key)).to eq time
|
@@ -57,7 +57,7 @@ describe Sidekiq::Merger::Redis do
|
|
57
57
|
let(:pushing_msg) { [1, 2, 3] }
|
58
58
|
let(:pushing_execution_time) { execution_time }
|
59
59
|
|
60
|
-
include_examples "
|
60
|
+
include_examples "push_message spec" do
|
61
61
|
let(:merge_keys) { ["foo"] }
|
62
62
|
let(:times) { {
|
63
63
|
"sidekiq-merger:time:foo" => execution_time.to_i.to_s,
|
@@ -72,8 +72,8 @@ describe Sidekiq::Merger::Redis do
|
|
72
72
|
|
73
73
|
context "the merge key already exists" do
|
74
74
|
let(:pushing_msg) { [2, 3, 4] }
|
75
|
-
before { subject.
|
76
|
-
include_examples "
|
75
|
+
before { subject.push_message("foo", [1, 2, 3], execution_time) }
|
76
|
+
include_examples "push_message spec" do
|
77
77
|
let(:merge_keys) { ["foo"] }
|
78
78
|
let(:times) { {
|
79
79
|
"sidekiq-merger:time:foo" => execution_time.to_i.to_s,
|
@@ -87,9 +87,9 @@ describe Sidekiq::Merger::Redis do
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
context "the
|
91
|
-
before { subject.
|
92
|
-
include_examples "
|
90
|
+
context "the msg has already ben pushed" do
|
91
|
+
before { subject.push_message("foo", [1, 2, 3], execution_time) }
|
92
|
+
include_examples "push_message spec" do
|
93
93
|
let(:merge_keys) { ["foo"] }
|
94
94
|
let(:times) { {
|
95
95
|
"sidekiq-merger:time:foo" => execution_time.to_i.to_s,
|
@@ -107,8 +107,8 @@ describe Sidekiq::Merger::Redis do
|
|
107
107
|
let(:pushing_key) { "bar" }
|
108
108
|
let(:pushing_msg) { [2, 3, 4] }
|
109
109
|
let(:pushing_execution_time) { execution_time + 1.hour }
|
110
|
-
before { subject.
|
111
|
-
include_examples "
|
110
|
+
before { subject.push_message("foo", [1, 2, 3], execution_time) }
|
111
|
+
include_examples "push_message spec" do
|
112
112
|
let(:merge_keys) { ["foo", "bar"] }
|
113
113
|
let(:times) { {
|
114
114
|
"sidekiq-merger:time:foo" => execution_time.to_i.to_s,
|
@@ -126,45 +126,112 @@ describe Sidekiq::Merger::Redis do
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
describe "#
|
129
|
+
describe "#delete_message" do
|
130
|
+
before do
|
131
|
+
subject.redis do |conn|
|
132
|
+
conn.sadd("sidekiq-merger:unique_msg:foo", "[1,2,3]")
|
133
|
+
conn.sadd("sidekiq-merger:unique_msg:foo", "[2,3,4]")
|
134
|
+
conn.lpush("sidekiq-merger:msg:foo", "[1,2,3]")
|
135
|
+
conn.lpush("sidekiq-merger:msg:foo", "[2,3,4]")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
it "deletes the msg" do
|
139
|
+
subject.delete_message("foo", [1, 2, 3])
|
140
|
+
subject.redis do |conn|
|
141
|
+
expect(conn.smembers("sidekiq-merger:unique_msg:foo")).to contain_exactly "[2,3,4]"
|
142
|
+
expect(conn.lrange("sidekiq-merger:msg:foo", 0, -1)).to contain_exactly "[2,3,4]"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
context "with duplicate msgs" do
|
146
|
+
it "deletes the msg" do
|
147
|
+
subject.redis do |conn|
|
148
|
+
conn.lpush("sidekiq-merger:msg:foo", "[1,2,3]")
|
149
|
+
end
|
150
|
+
subject.delete_message("foo", [1, 2, 3])
|
151
|
+
subject.redis do |conn|
|
152
|
+
expect(conn.smembers("sidekiq-merger:unique_msg:foo")).to contain_exactly "[2,3,4]"
|
153
|
+
expect(conn.lrange("sidekiq-merger:msg:foo", 0, -1)).to contain_exactly "[2,3,4]"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
130
157
|
end
|
131
158
|
|
132
159
|
describe "#merge_size" do
|
160
|
+
before do
|
161
|
+
subject.redis do |conn|
|
162
|
+
conn.lpush("sidekiq-merger:msg:foo", "[1,2,3]")
|
163
|
+
conn.lpush("sidekiq-merger:msg:foo", "[2,3,4]")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
it "returns the size" do
|
167
|
+
expect(subject.merge_size("foo")).to eq 2
|
168
|
+
end
|
133
169
|
end
|
134
170
|
|
135
|
-
describe "#
|
171
|
+
describe "#merge_exists?" do
|
136
172
|
context "unique key exists" do
|
137
173
|
it "returns true" do
|
138
174
|
described_class.redis { |conn| conn.sadd("sidekiq-merger:unique_msg:foo", "\"test\"") }
|
139
|
-
expect(subject.
|
175
|
+
expect(subject.merge_exists?("foo", "test")).to eq true
|
140
176
|
end
|
141
177
|
end
|
142
178
|
context "unique key does not exists" do
|
143
179
|
it "returns false" do
|
144
|
-
expect(subject.
|
180
|
+
expect(subject.merge_exists?("foo", "test")).to eq false
|
145
181
|
end
|
146
182
|
end
|
147
183
|
end
|
148
184
|
|
149
|
-
describe "#
|
185
|
+
describe "#all_merges" do
|
186
|
+
before do
|
187
|
+
subject.push_message("foo", [1, 2, 3], execution_time)
|
188
|
+
subject.push_message("bar", [2, 3, 4], execution_time)
|
189
|
+
end
|
190
|
+
it "gets all the merges" do
|
191
|
+
expect(subject.all_merges).to contain_exactly "foo", "bar"
|
192
|
+
end
|
150
193
|
end
|
151
194
|
|
152
|
-
describe "#
|
195
|
+
describe "#lock_merge" do
|
196
|
+
it "locks the key" do
|
197
|
+
subject.lock_merge("foo", 3)
|
198
|
+
subject.redis do |conn|
|
199
|
+
expect(conn.exists("sidekiq-merger:lock:foo")).to eq true
|
200
|
+
end
|
201
|
+
end
|
153
202
|
end
|
154
203
|
|
155
|
-
describe "#
|
204
|
+
describe "#get_merge" do
|
205
|
+
before do
|
206
|
+
subject.push_message("bar", [1, 2, 3], execution_time)
|
207
|
+
subject.push_message("bar", [2, 3, 4], execution_time)
|
208
|
+
end
|
209
|
+
it "gets all the msg" do
|
210
|
+
expect(subject.get_merge("bar")).to contain_exactly [1, 2, 3], [2, 3, 4]
|
211
|
+
expect(subject.merge_size("bar")).to eq 2
|
212
|
+
end
|
156
213
|
end
|
157
214
|
|
158
|
-
describe "#
|
215
|
+
describe "#pluck_merge" do
|
159
216
|
before do
|
160
|
-
subject.
|
161
|
-
subject.
|
217
|
+
subject.push_message("bar", [1, 2, 3], execution_time)
|
218
|
+
subject.push_message("bar", [2, 3, 4], execution_time)
|
162
219
|
end
|
163
|
-
it "plucks all the
|
164
|
-
expect(subject.
|
220
|
+
it "plucks all the msg" do
|
221
|
+
expect(subject.pluck_merge("bar")).to contain_exactly [1, 2, 3], [2, 3, 4]
|
222
|
+
expect(subject.merge_size("bar")).to eq 0
|
165
223
|
end
|
166
224
|
end
|
167
225
|
|
168
|
-
describe "#
|
226
|
+
describe "#delete_merge" do
|
227
|
+
before do
|
228
|
+
subject.push_message("foo", [1, 2, 3], execution_time)
|
229
|
+
subject.push_message("foo", [1, 2, 3], execution_time)
|
230
|
+
end
|
231
|
+
it "deletes the merge" do
|
232
|
+
expect {
|
233
|
+
subject.delete_merge("foo")
|
234
|
+
}.to change { subject.merge_size("foo") }.from(2).to(0)
|
235
|
+
end
|
169
236
|
end
|
170
237
|
end
|