sidekiq-debouncer 1.0.1
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 +7 -0
- data/.gitignore +19 -0
- data/.semaphore/semaphore.yml +27 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +95 -0
- data/gemfiles/sidekiq-5.0.5.gemfile +7 -0
- data/gemfiles/sidekiq-5.1.3.gemfile +7 -0
- data/gemfiles/sidekiq-5.2.7.gemfile +7 -0
- data/gemfiles/sidekiq-6.0.2.gemfile +7 -0
- data/lib/sidekiq/debouncer.rb +48 -0
- data/lib/sidekiq/debouncer/version.rb +5 -0
- data/sidekiq-debounce.gemspec +28 -0
- data/spec/sidekiq/debouncer_spec.rb +202 -0
- data/spec/spec_helper.rb +18 -0
- metadata +159 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9f505c753200cb5a607d4a0f847372a72f5f5571631d6b50e12348e99b407f30
|
4
|
+
data.tar.gz: b72d1d31b9b1b13a7ab8ec88a56a27e2a84e11a8dca721e296ec4a25da361dd7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 400505251465ceca2630d226a8f1017518a5bb068e755a05428e8f00be81519c2ddcda91be840c24f3eaf382ff7302e1c1941fe790eec95a5cb9f9d9f72dd797
|
7
|
+
data.tar.gz: 6d01faab4b9f4b98512dadb598100674d241ab3fd99a324e1abb89773a9a4c92ba8782fb1564e68a97d4c171646ec9f6472a25cdb507eba218d739f368f1226f
|
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
version: v1.0
|
2
|
+
name: Sidekiq-debouncer CI pipeline
|
3
|
+
agent:
|
4
|
+
machine:
|
5
|
+
type: e1-standard-2
|
6
|
+
os_image: ubuntu1804
|
7
|
+
|
8
|
+
blocks:
|
9
|
+
- name: Run specs
|
10
|
+
task:
|
11
|
+
env_vars:
|
12
|
+
- name: RAILS_ENV
|
13
|
+
value: "test"
|
14
|
+
|
15
|
+
jobs:
|
16
|
+
- name: Run RSpec
|
17
|
+
matrix:
|
18
|
+
- env_var: SIDEKIQ_VERSION
|
19
|
+
values: [ "5.0.5", "5.1.3", "5.2.7", "6.0.2" ]
|
20
|
+
commands:
|
21
|
+
- checkout
|
22
|
+
- export RUBY_VERSION=$(cat gemfiles/sidekiq-$SIDEKIQ_VERSION.gemfile | grep "ruby \".*\"" | grep -o "[0-9]\.[0-9]\.[0-9]")
|
23
|
+
- sem-version ruby $RUBY_VERSION
|
24
|
+
- sem-service start redis
|
25
|
+
- gem install bundler -v 1.17.3 -N
|
26
|
+
- bundle install --gemfile gemfiles/sidekiq-$SIDEKIQ_VERSION.gemfile
|
27
|
+
- RAILS_ENV=test bundle exec --gemfile gemfiles/sidekiq-$SIDEKIQ_VERSION.gemfile rspec
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Gabriel Evans
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Sidekiq::Debouncer
|
2
|
+
|
3
|
+
Sidekiq extension that adds the ability to debounce job execution.
|
4
|
+
|
5
|
+
Worker will postpone its execution after `wait time` have elapsed since the last time it was invoked. Useful for implementing behavior that should only happen after the input has stopped arriving. For example: sending group email to the user after he stopped interacting with the application.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'sidekiq-debouncer'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
## Basic usage
|
20
|
+
|
21
|
+
In a worker, include `Sidekiq::Debouncer` module, specify debounce wait time (in seconds):
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class MyWorker
|
25
|
+
include Sidekiq::Worker
|
26
|
+
include Sidekiq::Debouncer
|
27
|
+
|
28
|
+
sidekiq_options(
|
29
|
+
debounce: {
|
30
|
+
time: 5 * 60
|
31
|
+
}
|
32
|
+
)
|
33
|
+
|
34
|
+
def perform(group)
|
35
|
+
group.each do
|
36
|
+
# do some work with group
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
You can specify your own debounce method. In this case worker will be debounced if first argument matches.
|
43
|
+
```ruby
|
44
|
+
class MyWorker
|
45
|
+
include Sidekiq::Worker
|
46
|
+
include Sidekiq::Debouncer
|
47
|
+
|
48
|
+
sidekiq_options(
|
49
|
+
debounce: {
|
50
|
+
time: 5 * 60,
|
51
|
+
by: -> (job_args) {
|
52
|
+
job_args[0]
|
53
|
+
}
|
54
|
+
}
|
55
|
+
)
|
56
|
+
|
57
|
+
def perform(group)
|
58
|
+
group.each do
|
59
|
+
# do some work with group
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
You can also pass symbol as `debounce_by` matching class method.
|
66
|
+
```ruby
|
67
|
+
class MyWorker
|
68
|
+
include Sidekiq::Worker
|
69
|
+
include Sidekiq::Debouncer
|
70
|
+
|
71
|
+
sidekiq_options(
|
72
|
+
debounce: {
|
73
|
+
time: 5 * 60,
|
74
|
+
by: :debounce_method
|
75
|
+
}
|
76
|
+
)
|
77
|
+
|
78
|
+
def self.debounce_method(job_args)
|
79
|
+
job_args[0]
|
80
|
+
end
|
81
|
+
|
82
|
+
def perform(group)
|
83
|
+
group.each do
|
84
|
+
# do some work with group
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
|
91
|
+
In the application, call `MyWorker.debounce(...)`. Everytime you call this function, `MyWorker`'s execution will be postponed by 5 minutes. After that time `MyWorker` will receive a method call `perform` with an array of arguments that were provided to the `MyWorker.debounce(...)`.
|
92
|
+
|
93
|
+
## License
|
94
|
+
|
95
|
+
MIT Licensed. See LICENSE.txt for details.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'sidekiq'
|
2
|
+
require 'sidekiq/api'
|
3
|
+
|
4
|
+
require 'sidekiq/debouncer/version'
|
5
|
+
|
6
|
+
module Sidekiq
|
7
|
+
module Debouncer
|
8
|
+
def self.included(base)
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
DEFAULT_DEBOUNCE_FOR = 5 * 60 # 5.minutes
|
14
|
+
DEFAULT_DEBOUNCE_BY = -> (job_args) { 0 }
|
15
|
+
|
16
|
+
def debounce(*args)
|
17
|
+
sidekiq_options["debounce"] ||= {}
|
18
|
+
|
19
|
+
debounce_for = sidekiq_options["debounce"][:time] || DEFAULT_DEBOUNCE_FOR
|
20
|
+
debounce_by = sidekiq_options["debounce"][:by] || DEFAULT_DEBOUNCE_BY
|
21
|
+
debounce_by_value = debounce_by.is_a?(Symbol) ? send(debounce_by, args) : debounce_by.call(args)
|
22
|
+
|
23
|
+
ss = Sidekiq::ScheduledSet.new
|
24
|
+
jobs = ss.select do |job|
|
25
|
+
next false unless job.klass == self.to_s
|
26
|
+
|
27
|
+
debounce_by_value_job = debounce_by.is_a?(Symbol) ? send(debounce_by, job.args[0][0]) : debounce_by.call(job.args[0][0])
|
28
|
+
|
29
|
+
debounce_by_value_job == debounce_by_value
|
30
|
+
end
|
31
|
+
|
32
|
+
time_from_now = Time.now + debounce_for
|
33
|
+
jobs_to_group = []
|
34
|
+
|
35
|
+
jobs.each do |job|
|
36
|
+
if job.at > Time.now && job.at < time_from_now
|
37
|
+
jobs_to_group += job.args[0]
|
38
|
+
job.delete
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
jobs_to_group << args
|
43
|
+
|
44
|
+
perform_in(debounce_for, jobs_to_group)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sidekiq/debouncer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'sidekiq-debouncer'
|
8
|
+
gem.version = Sidekiq::Debouncer::VERSION
|
9
|
+
gem.authors = ['Sebastian Zuchmański', 'Karol Bąk']
|
10
|
+
gem.email = ['sebcioz@gmail.com', 'karol.bak@paladinsoftware.com']
|
11
|
+
gem.description = %q{Sidekiq extension that adds the ability to debounce job execution.}
|
12
|
+
gem.summary = %q{}
|
13
|
+
gem.homepage = 'https://github.com/paladinsoftware/sidekiq-debouncer'
|
14
|
+
gem.license = 'MIT'
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = %w(lib)
|
19
|
+
|
20
|
+
gem.add_dependency 'activesupport'
|
21
|
+
gem.add_dependency 'sidekiq', '>= 5.0'
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rspec'
|
24
|
+
gem.add_development_dependency 'rspec-sidekiq'
|
25
|
+
gem.add_development_dependency 'timecop'
|
26
|
+
gem.add_development_dependency 'rspec-redis_helper'
|
27
|
+
gem.add_development_dependency 'redis-namespace'
|
28
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestWorker
|
4
|
+
include Sidekiq::Worker
|
5
|
+
include Sidekiq::Debouncer
|
6
|
+
|
7
|
+
sidekiq_options(
|
8
|
+
debounce: {
|
9
|
+
time: 5 * 60,
|
10
|
+
by: -> (job_args) {
|
11
|
+
job_args[0]
|
12
|
+
}
|
13
|
+
}
|
14
|
+
)
|
15
|
+
|
16
|
+
# group - array of arguments for single job
|
17
|
+
def perform(group)
|
18
|
+
group.each do
|
19
|
+
# do some work with group
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class TestWorkerWithMultipleArguments
|
25
|
+
include Sidekiq::Worker
|
26
|
+
include Sidekiq::Debouncer
|
27
|
+
|
28
|
+
sidekiq_options(
|
29
|
+
debounce: {
|
30
|
+
time: 5 * 60,
|
31
|
+
by: -> (job_args) {
|
32
|
+
job_args[0] + job_args[1]
|
33
|
+
}
|
34
|
+
}
|
35
|
+
)
|
36
|
+
|
37
|
+
# group - array of arguments for single job
|
38
|
+
def perform(group)
|
39
|
+
group.each do
|
40
|
+
# do some work with group
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class TestWorkerWithSymbolAsDebounce
|
46
|
+
include Sidekiq::Worker
|
47
|
+
include Sidekiq::Debouncer
|
48
|
+
|
49
|
+
sidekiq_options(
|
50
|
+
debounce: {
|
51
|
+
time: 5 * 60,
|
52
|
+
by: :debounce_method
|
53
|
+
}
|
54
|
+
)
|
55
|
+
|
56
|
+
def self.debounce_method(args)
|
57
|
+
args[0]
|
58
|
+
end
|
59
|
+
|
60
|
+
# group - array of arguments for single job
|
61
|
+
def perform(group)
|
62
|
+
group.each do
|
63
|
+
# do some work with group
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe Sidekiq::Debouncer do
|
69
|
+
let(:time_start) { Time.new(2016, 1, 1, 12, 0, 0) }
|
70
|
+
|
71
|
+
before do
|
72
|
+
Timecop.freeze(time_start)
|
73
|
+
Sidekiq::ScheduledSet.new.clear
|
74
|
+
Sidekiq::Testing.disable!
|
75
|
+
end
|
76
|
+
|
77
|
+
context "1 type of tasks" do
|
78
|
+
context "1 task" do
|
79
|
+
it "executes it after 5 minutes" do
|
80
|
+
TestWorker.debounce("A", "job 1")
|
81
|
+
|
82
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(1)
|
83
|
+
|
84
|
+
group = Sidekiq::ScheduledSet.new.first
|
85
|
+
expect(group.args[0]).to eq([["A", "job 1"]])
|
86
|
+
expect(group.at.to_i).to eq((time_start + 5 * 60).to_i)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "executes it after 5 minutes for symbol debounce" do
|
90
|
+
expect(TestWorkerWithSymbolAsDebounce).to receive(:debounce_method).with(["A", "job 1"]).once.and_call_original
|
91
|
+
TestWorkerWithSymbolAsDebounce.debounce("A", "job 1")
|
92
|
+
|
93
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(1)
|
94
|
+
|
95
|
+
group = Sidekiq::ScheduledSet.new.first
|
96
|
+
expect(group.args[0]).to eq([["A", "job 1"]])
|
97
|
+
expect(group.at.to_i).to eq((time_start + 5 * 60).to_i)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "1 task, 3 minutes break, 1 task" do
|
102
|
+
it "executes both tasks after 8 minutes for multiple arguments" do
|
103
|
+
TestWorkerWithMultipleArguments.debounce(1, 5)
|
104
|
+
Timecop.freeze(time_start + 3 * 60)
|
105
|
+
TestWorkerWithMultipleArguments.debounce(3, 3)
|
106
|
+
|
107
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(1)
|
108
|
+
group = Sidekiq::ScheduledSet.new.first
|
109
|
+
expect(group.args[0]).to eq([[1, 5], [3, 3]])
|
110
|
+
expect(group.at.to_i).to be((time_start + 8 * 60).to_i)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "executes both tasks after 8 minutes" do
|
114
|
+
TestWorker.debounce("A", "job 1")
|
115
|
+
Timecop.freeze(time_start + 3 * 60)
|
116
|
+
TestWorker.debounce("A", "job 2")
|
117
|
+
|
118
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(1)
|
119
|
+
group = Sidekiq::ScheduledSet.new.first
|
120
|
+
expect(group.args[0]).to eq([["A", "job 1"], ["A", "job 2"]])
|
121
|
+
expect(group.at.to_i).to be((time_start + 8 * 60).to_i)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "executes both tasks after 8 minutes for symbol debounce" do
|
125
|
+
TestWorkerWithSymbolAsDebounce.debounce("A", "job 1")
|
126
|
+
Timecop.freeze(time_start + 3 * 60)
|
127
|
+
TestWorkerWithSymbolAsDebounce.debounce("A", "job 2")
|
128
|
+
|
129
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(1)
|
130
|
+
group = Sidekiq::ScheduledSet.new.first
|
131
|
+
expect(group.args[0]).to eq([["A", "job 1"], ["A", "job 2"]])
|
132
|
+
expect(group.at.to_i).to be((time_start + 8 * 60).to_i)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "1 task, 3 minutes break, 1 task, 6 minutes break, 1 task" do
|
137
|
+
it "executes two tasks after 8 minutes, the last one in 14 minutes" do
|
138
|
+
TestWorker.debounce("A", "job 1")
|
139
|
+
Timecop.freeze(time_start + 3 * 60)
|
140
|
+
TestWorker.debounce("A", "job 2")
|
141
|
+
Timecop.freeze(time_start + 3 * 60 + 6 * 60)
|
142
|
+
TestWorker.debounce("A", "job 3")
|
143
|
+
|
144
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(2)
|
145
|
+
|
146
|
+
groups = Sidekiq::ScheduledSet.new.to_a.sort_by { |g| g.at.to_i }
|
147
|
+
|
148
|
+
expect(groups[0].args[0]).to eq([["A", "job 1"], ["A", "job 2"]])
|
149
|
+
expect(groups[0].at.to_i).to be((time_start + 8 * 60).to_i)
|
150
|
+
|
151
|
+
expect(groups[1].args[0]).to eq([["A", "job 3"]])
|
152
|
+
expect(groups[1].at.to_i).to be((time_start + 14 * 60).to_i)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "1 task, 6 minutes break, 1 task" do
|
157
|
+
it "executes first task, the second one in 11 minutes" do
|
158
|
+
TestWorker.debounce("A", "job 1")
|
159
|
+
Timecop.freeze(time_start + 6 * 60)
|
160
|
+
TestWorker.debounce("A", "job 2")
|
161
|
+
|
162
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(2)
|
163
|
+
|
164
|
+
groups = Sidekiq::ScheduledSet.new.to_a.sort_by { |g| g.at.to_i }
|
165
|
+
|
166
|
+
expect(groups[0].args[0]).to eq([["A", "job 1"]])
|
167
|
+
expect(groups[0].at.to_i).to be((time_start + 5 * 60).to_i)
|
168
|
+
|
169
|
+
expect(groups[1].args[0]).to eq([["A", "job 2"]])
|
170
|
+
expect(groups[1].at.to_i).to be((time_start + 11 * 60).to_i)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "two types of tasks" do
|
176
|
+
context "A task, 3 minutes break, A and B tasks, 3 minutes break, B task, 6 minutes break, B task" do
|
177
|
+
it "executes two A tasks after 8 minuts, two B tasks after 11 minutes, last B task after 17 minutes" do
|
178
|
+
TestWorker.debounce("A", "job 1")
|
179
|
+
Timecop.freeze(time_start + 3 * 60)
|
180
|
+
TestWorker.debounce("A", "job 2")
|
181
|
+
TestWorker.debounce("B", "job 3")
|
182
|
+
Timecop.freeze(time_start + 3 * 60 + 3 * 60)
|
183
|
+
TestWorker.debounce("B", "job 4")
|
184
|
+
Timecop.freeze(time_start + 3 * 60 + 3 * 60 + 6 * 60)
|
185
|
+
TestWorker.debounce("B", "job 5")
|
186
|
+
|
187
|
+
expect(Sidekiq::ScheduledSet.new.size).to eq(3)
|
188
|
+
|
189
|
+
groups = Sidekiq::ScheduledSet.new.to_a.sort_by { |g| g.at.to_i }
|
190
|
+
|
191
|
+
expect(groups[0].args[0]).to eq([["A", "job 1"], ["A", "job 2"]])
|
192
|
+
expect(groups[0].at.to_i).to be((time_start + 8 * 60).to_i)
|
193
|
+
|
194
|
+
expect(groups[1].args[0]).to eq([["B", "job 3"], ["B", "job 4"]])
|
195
|
+
expect(groups[1].at.to_i).to be((time_start + 11 * 60).to_i)
|
196
|
+
|
197
|
+
expect(groups[2].args[0]).to eq([["B", "job 5"]])
|
198
|
+
expect(groups[2].at.to_i).to be((time_start + 17 * 60).to_i)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'redis/namespace'
|
6
|
+
require 'rspec-sidekiq'
|
7
|
+
require 'timecop'
|
8
|
+
|
9
|
+
require 'sidekiq/debouncer'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.order = 'random'
|
13
|
+
config.color = true
|
14
|
+
|
15
|
+
Sidekiq.configure_server do |config|
|
16
|
+
config.redis[:namespace] = { namespace: 'sidekiq-debouncer' }
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sidekiq-debouncer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sebastian Zuchmański
|
8
|
+
- Karol Bąk
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2019-10-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: sidekiq
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5.0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '5.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec-sidekiq
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: timecop
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec-redis_helper
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: redis-namespace
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
description: Sidekiq extension that adds the ability to debounce job execution.
|
113
|
+
email:
|
114
|
+
- sebcioz@gmail.com
|
115
|
+
- karol.bak@paladinsoftware.com
|
116
|
+
executables: []
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".gitignore"
|
121
|
+
- ".semaphore/semaphore.yml"
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- gemfiles/sidekiq-5.0.5.gemfile
|
126
|
+
- gemfiles/sidekiq-5.1.3.gemfile
|
127
|
+
- gemfiles/sidekiq-5.2.7.gemfile
|
128
|
+
- gemfiles/sidekiq-6.0.2.gemfile
|
129
|
+
- lib/sidekiq/debouncer.rb
|
130
|
+
- lib/sidekiq/debouncer/version.rb
|
131
|
+
- sidekiq-debounce.gemspec
|
132
|
+
- spec/sidekiq/debouncer_spec.rb
|
133
|
+
- spec/spec_helper.rb
|
134
|
+
homepage: https://github.com/paladinsoftware/sidekiq-debouncer
|
135
|
+
licenses:
|
136
|
+
- MIT
|
137
|
+
metadata: {}
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubygems_version: 3.0.6
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: ''
|
157
|
+
test_files:
|
158
|
+
- spec/sidekiq/debouncer_spec.rb
|
159
|
+
- spec/spec_helper.rb
|