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.
@@ -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
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .rspec-local
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ gemfiles/*.gemfile.lock
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
@@ -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
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -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.
@@ -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,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby "2.3.8"
4
+
5
+ gem "sidekiq", "= 5.0.5"
6
+
7
+ gemspec path: '../'
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby "2.4.6"
4
+
5
+ gem "sidekiq", "= 5.1.3"
6
+
7
+ gemspec path: '../'
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby "2.5.5"
4
+
5
+ gem "sidekiq", "= 5.2.7"
6
+
7
+ gemspec path: '../'
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby "2.6.5"
4
+
5
+ gem "sidekiq", "= 6.0.2"
6
+
7
+ gemspec path: '../'
@@ -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,5 @@
1
+ module Sidekiq
2
+ module Debouncer
3
+ VERSION = '1.0.1'.freeze
4
+ end
5
+ 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
@@ -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