sidekiq-merger 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|