sidekiq-debounce 1.0.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 +7 -0
- data/.editorconfig +10 -0
- data/.gitignore +14 -0
- data/.hound.yml +2 -0
- data/.rubocop.yml +259 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +7 -0
- data/lib/sidekiq/debounce.rb +52 -0
- data/lib/sidekiq/debounce/version.rb +5 -0
- data/sidekiq-debounce.gemspec +34 -0
- data/spec/sidekiq/debounce_spec.rb +53 -0
- data/spec/sidekiq_helper.rb +13 -0
- data/spec/spec_helper.rb +7 -0
- metadata +152 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 52ea839929c2e0277e8236cab80a64b00c65cf76
|
|
4
|
+
data.tar.gz: 60714587a6390bcc45f422b1d80606e8b3192cad
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 99cde08138a0ad4dada1b1fa728e4c55f4919205265969dc218b2e74d3851f1320b615f4159eec7c7dda034c447dc1b43b977e47eaf885ba8a3c64ae71513653
|
|
7
|
+
data.tar.gz: a9bf32f2596ddb3365bdae2eeefc9e79ef70942ae57e0ae3d626e68eabd321c32c0cee889a05f6cb508f9277dc71cc37a775e8746d49325024a7b557f74479e8
|
data/.editorconfig
ADDED
data/.gitignore
ADDED
data/.hound.yml
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
RunRailsCops: false
|
|
3
|
+
DisplayCopNames: false
|
|
4
|
+
DisplayStyleGuide: true
|
|
5
|
+
StyleGuideCopsOnly: false
|
|
6
|
+
Style/BlockDelimiters:
|
|
7
|
+
EnforcedStyle: semantic
|
|
8
|
+
Style/CollectionMethods:
|
|
9
|
+
PreferredMethods:
|
|
10
|
+
collect: map
|
|
11
|
+
collect!: map!
|
|
12
|
+
inject: reduce
|
|
13
|
+
detect: find
|
|
14
|
+
find_all: select
|
|
15
|
+
Style/CommentAnnotation:
|
|
16
|
+
Enabled: true
|
|
17
|
+
Keywords:
|
|
18
|
+
- TODO
|
|
19
|
+
- FIXME
|
|
20
|
+
- OPTIMIZE
|
|
21
|
+
- HACK
|
|
22
|
+
- REVIEW
|
|
23
|
+
- DEPRECATED
|
|
24
|
+
Style/DotPosition:
|
|
25
|
+
EnforcedStyle: leading
|
|
26
|
+
Style/FileName:
|
|
27
|
+
Enabled: true
|
|
28
|
+
Style/FormatString:
|
|
29
|
+
Enabled: true
|
|
30
|
+
EnforcedStyle: format
|
|
31
|
+
Style/GlobalVars:
|
|
32
|
+
Enabled: true
|
|
33
|
+
Style/GuardClause:
|
|
34
|
+
Enabled: true
|
|
35
|
+
MinBodyLength: 3
|
|
36
|
+
Style/IfUnlessModifier:
|
|
37
|
+
Enabled: true
|
|
38
|
+
MaxLineLength: 80
|
|
39
|
+
Style/LambdaCall:
|
|
40
|
+
Enabled: true
|
|
41
|
+
Style/Next:
|
|
42
|
+
Enabled: true
|
|
43
|
+
MinBodyLength: 3
|
|
44
|
+
Style/NumericLiterals:
|
|
45
|
+
Enabled: true
|
|
46
|
+
MinDigits: 5
|
|
47
|
+
Style/PercentLiteralDelimiters:
|
|
48
|
+
Enabled: true
|
|
49
|
+
PreferredDelimiters:
|
|
50
|
+
"%": "()"
|
|
51
|
+
"%i": "()"
|
|
52
|
+
"%q": "()"
|
|
53
|
+
"%Q": "()"
|
|
54
|
+
"%r": "{}"
|
|
55
|
+
"%s": "()"
|
|
56
|
+
"%w": "()"
|
|
57
|
+
"%W": "()"
|
|
58
|
+
"%x": "()"
|
|
59
|
+
Style/PredicateName:
|
|
60
|
+
Enabled: true
|
|
61
|
+
NamePrefix:
|
|
62
|
+
- is_
|
|
63
|
+
- has_
|
|
64
|
+
- have_
|
|
65
|
+
NamePrefixBlacklist:
|
|
66
|
+
- is_
|
|
67
|
+
Style/RaiseArgs:
|
|
68
|
+
Enabled: true
|
|
69
|
+
EnforcedStyle: exploded
|
|
70
|
+
Style/SingleLineMethods:
|
|
71
|
+
Enabled: true
|
|
72
|
+
AllowIfMethodIsEmpty: true
|
|
73
|
+
Style/StringLiterals:
|
|
74
|
+
EnforcedStyle: single_quotes
|
|
75
|
+
Style/SpaceAroundEqualsInParameterDefault:
|
|
76
|
+
Enabled: true
|
|
77
|
+
EnforcedStyle: space
|
|
78
|
+
Style/SpaceBeforeBlockBraces:
|
|
79
|
+
Enabled: true
|
|
80
|
+
EnforcedStyle: space
|
|
81
|
+
Style/SpaceInsideBlockBraces:
|
|
82
|
+
Enabled: true
|
|
83
|
+
EnforcedStyle: space
|
|
84
|
+
EnforcedStyleForEmptyBraces: no_space
|
|
85
|
+
SpaceBeforeBlockParameters: true
|
|
86
|
+
Style/SpaceInsideHashLiteralBraces:
|
|
87
|
+
Enabled: true
|
|
88
|
+
EnforcedStyle: space
|
|
89
|
+
EnforcedStyleForEmptyBraces: no_space
|
|
90
|
+
Style/SymbolProc:
|
|
91
|
+
Enabled: true
|
|
92
|
+
Style/TrailingBlankLines:
|
|
93
|
+
Enabled: true
|
|
94
|
+
EnforcedStyle: final_newline
|
|
95
|
+
Style/TrailingComma:
|
|
96
|
+
Enabled: true
|
|
97
|
+
EnforcedStyleForMultiline: comma
|
|
98
|
+
Style/TrivialAccessors:
|
|
99
|
+
Enabled: true
|
|
100
|
+
AllowDSLWriters: true
|
|
101
|
+
Style/VariableName:
|
|
102
|
+
Enabled: true
|
|
103
|
+
EnforcedStyle: snake_case
|
|
104
|
+
Style/WordArray:
|
|
105
|
+
Enabled: true
|
|
106
|
+
MinSize: 2
|
|
107
|
+
Metrics/AbcSize:
|
|
108
|
+
Enabled: true
|
|
109
|
+
Max: 25
|
|
110
|
+
Metrics/BlockNesting:
|
|
111
|
+
Enabled: true
|
|
112
|
+
Max: 5
|
|
113
|
+
Metrics/ClassLength:
|
|
114
|
+
Enabled: true
|
|
115
|
+
CountComments: false
|
|
116
|
+
Max: 500
|
|
117
|
+
Metrics/CyclomaticComplexity:
|
|
118
|
+
Enabled: true
|
|
119
|
+
Max: 10
|
|
120
|
+
Metrics/LineLength:
|
|
121
|
+
Enabled: true
|
|
122
|
+
Max: 80
|
|
123
|
+
AllowURI: true
|
|
124
|
+
Metrics/MethodLength:
|
|
125
|
+
Enabled: true
|
|
126
|
+
CountComments: false
|
|
127
|
+
Max: 20
|
|
128
|
+
Metrics/ParameterLists:
|
|
129
|
+
Enabled: true
|
|
130
|
+
Max: 5
|
|
131
|
+
CountKeywordArgs: false
|
|
132
|
+
Metrics/PerceivedComplexity:
|
|
133
|
+
Enabled: true
|
|
134
|
+
Max: 8
|
|
135
|
+
Lint/AssignmentInCondition:
|
|
136
|
+
Enabled: true
|
|
137
|
+
AllowSafeAssignment: true
|
|
138
|
+
Style/InlineComment:
|
|
139
|
+
Enabled: false
|
|
140
|
+
Style/MethodCalledOnDoEndBlock:
|
|
141
|
+
Enabled: true
|
|
142
|
+
Style/SymbolArray:
|
|
143
|
+
Enabled: true
|
|
144
|
+
Style/AccessorMethodName:
|
|
145
|
+
Enabled: true
|
|
146
|
+
Style/Alias:
|
|
147
|
+
Enabled: true
|
|
148
|
+
Style/ArrayJoin:
|
|
149
|
+
Enabled: true
|
|
150
|
+
Style/AsciiComments:
|
|
151
|
+
Enabled: true
|
|
152
|
+
Style/AsciiIdentifiers:
|
|
153
|
+
Enabled: true
|
|
154
|
+
Style/Attr:
|
|
155
|
+
Enabled: true
|
|
156
|
+
Style/BlockComments:
|
|
157
|
+
Enabled: true
|
|
158
|
+
Style/ColonMethodCall:
|
|
159
|
+
Enabled: true
|
|
160
|
+
Style/DeprecatedHashMethods:
|
|
161
|
+
Enabled: true
|
|
162
|
+
Style/Documentation:
|
|
163
|
+
Enabled: false
|
|
164
|
+
Style/EmptyLiteral:
|
|
165
|
+
Enabled: true
|
|
166
|
+
Style/EvenOdd:
|
|
167
|
+
Enabled: true
|
|
168
|
+
Style/FlipFlop:
|
|
169
|
+
Enabled: true
|
|
170
|
+
Style/IfWithSemicolon:
|
|
171
|
+
Enabled: true
|
|
172
|
+
Style/Lambda:
|
|
173
|
+
Enabled: true
|
|
174
|
+
Style/LeadingCommentSpace:
|
|
175
|
+
Enabled: true
|
|
176
|
+
Style/MultilineBlockChain:
|
|
177
|
+
Enabled: true
|
|
178
|
+
Style/MultilineTernaryOperator:
|
|
179
|
+
Enabled: true
|
|
180
|
+
Style/NegatedIf:
|
|
181
|
+
Enabled: true
|
|
182
|
+
Style/NestedTernaryOperator:
|
|
183
|
+
Enabled: true
|
|
184
|
+
Style/NilComparison:
|
|
185
|
+
Enabled: true
|
|
186
|
+
Style/Not:
|
|
187
|
+
Enabled: true
|
|
188
|
+
Style/OneLineConditional:
|
|
189
|
+
Enabled: true
|
|
190
|
+
Style/PerlBackrefs:
|
|
191
|
+
Enabled: true
|
|
192
|
+
Style/RedundantBegin:
|
|
193
|
+
Enabled: true
|
|
194
|
+
Style/RedundantSelf:
|
|
195
|
+
Enabled: true
|
|
196
|
+
Style/RescueModifier:
|
|
197
|
+
Enabled: true
|
|
198
|
+
Style/SelfAssignment:
|
|
199
|
+
Enabled: true
|
|
200
|
+
Style/SingleSpaceBeforeFirstArg:
|
|
201
|
+
Enabled: true
|
|
202
|
+
Style/SpaceAfterColon:
|
|
203
|
+
Enabled: true
|
|
204
|
+
Style/SpaceAfterComma:
|
|
205
|
+
Enabled: true
|
|
206
|
+
Style/SpaceAfterControlKeyword:
|
|
207
|
+
Enabled: true
|
|
208
|
+
Style/SpaceAfterMethodName:
|
|
209
|
+
Enabled: true
|
|
210
|
+
Style/SpaceAfterNot:
|
|
211
|
+
Enabled: true
|
|
212
|
+
Style/SpaceAfterSemicolon:
|
|
213
|
+
Enabled: true
|
|
214
|
+
Style/SpaceBeforeComma:
|
|
215
|
+
Enabled: true
|
|
216
|
+
Style/SpaceBeforeComment:
|
|
217
|
+
Enabled: true
|
|
218
|
+
Style/SpaceBeforeSemicolon:
|
|
219
|
+
Enabled: true
|
|
220
|
+
Style/SpaceAroundOperators:
|
|
221
|
+
Enabled: true
|
|
222
|
+
Style/SpaceBeforeModifierKeyword:
|
|
223
|
+
Enabled: true
|
|
224
|
+
Style/SpaceInsideBrackets:
|
|
225
|
+
Enabled: true
|
|
226
|
+
Style/SpaceInsideParens:
|
|
227
|
+
Enabled: true
|
|
228
|
+
Style/SpaceInsideRangeLiteral:
|
|
229
|
+
Enabled: true
|
|
230
|
+
Style/SpecialGlobalVars:
|
|
231
|
+
Enabled: true
|
|
232
|
+
Style/TrailingWhitespace:
|
|
233
|
+
Enabled: true
|
|
234
|
+
Style/UnlessElse:
|
|
235
|
+
Enabled: true
|
|
236
|
+
Style/VariableInterpolation:
|
|
237
|
+
Enabled: true
|
|
238
|
+
Style/WhenThen:
|
|
239
|
+
Enabled: true
|
|
240
|
+
Lint/Debugger:
|
|
241
|
+
Enabled: true
|
|
242
|
+
Lint/DeprecatedClassMethods:
|
|
243
|
+
Enabled: true
|
|
244
|
+
Lint/Eval:
|
|
245
|
+
Enabled: true
|
|
246
|
+
Lint/HandleExceptions:
|
|
247
|
+
Enabled: true
|
|
248
|
+
Lint/LiteralInInterpolation:
|
|
249
|
+
Enabled: true
|
|
250
|
+
Lint/Loop:
|
|
251
|
+
Enabled: true
|
|
252
|
+
Lint/ParenthesesAsGroupedExpression:
|
|
253
|
+
Enabled: true
|
|
254
|
+
Lint/RequireParentheses:
|
|
255
|
+
Enabled: false
|
|
256
|
+
Lint/UnderscorePrefixedVariableName:
|
|
257
|
+
Enabled: true
|
|
258
|
+
Lint/UselessSetterCall:
|
|
259
|
+
Enabled: true
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015 Peter Lejeck
|
|
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,47 @@
|
|
|
1
|
+
Sidekiq::Debounce
|
|
2
|
+
=================
|
|
3
|
+
[](https://travis-ci.org/NuckChorris/sidekiq-debounce)
|
|
4
|
+
[](https://codeclimate.com/github/NuckChorris/sidekiq-debounce)
|
|
5
|
+
[](https://codeclimate.com/github/NuckChorris/sidekiq-debounce)
|
|
6
|
+
[](https://rubygems.org/gems/sidekiq-debounce)
|
|
7
|
+
[](https://www.gittip.com/Nuck/)
|
|
8
|
+
|
|
9
|
+
Sidekiq::Debounce is a client-side Sidekiq middleware which provides a way to
|
|
10
|
+
easily rate-limit creation of Sidekiq jobs.
|
|
11
|
+
|
|
12
|
+
When you create a job via `#perform_in` on a Worker with debounce enabled,
|
|
13
|
+
Sidekiq::Debounce will prevent other jobs with the same arguments from being
|
|
14
|
+
created until the job has run. Every time you create another job with those
|
|
15
|
+
same arguments prior to the job being run, the timer is reset and the entire
|
|
16
|
+
period must pass again before the job is executed.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Add this line to your application's Gemfile:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
gem 'sidekiq-debounce'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
And then execute:
|
|
27
|
+
|
|
28
|
+
$ bundle
|
|
29
|
+
|
|
30
|
+
Or install it yourself as:
|
|
31
|
+
|
|
32
|
+
$ gem install sidekiq-debounce
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
Add `Sidekiq::Debounce` to your client middleware chain, and then add
|
|
37
|
+
`sidekiq_options debounce: true` to the worker you wish to debounce.
|
|
38
|
+
|
|
39
|
+
Use `#perform_in` instead of `#perform_async` to set the timeframe.
|
|
40
|
+
|
|
41
|
+
## Contributing
|
|
42
|
+
|
|
43
|
+
1. Fork it ( https://github.com/nuckchorris/sidekiq-debounce/fork )
|
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
47
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'sidekiq/debounce/version'
|
|
2
|
+
require 'sidekiq/api'
|
|
3
|
+
|
|
4
|
+
module Sidekiq
|
|
5
|
+
class Debounce
|
|
6
|
+
def call(worker, msg, _queue, redis_pool)
|
|
7
|
+
@worker = worker
|
|
8
|
+
@msg = msg
|
|
9
|
+
|
|
10
|
+
return yield unless debounce?
|
|
11
|
+
|
|
12
|
+
redis_pool.with do |conn|
|
|
13
|
+
# Get JID of the already-scheduled job, if there is one
|
|
14
|
+
scheduled_jid = conn.get(debounce_key)
|
|
15
|
+
|
|
16
|
+
# Reschedule the old job to when this new job is scheduled for
|
|
17
|
+
# Or yield if there isn't one scheduled yet
|
|
18
|
+
jid = scheduled_jid ? reschedule(scheduled_jid, @msg['at']) : yield
|
|
19
|
+
|
|
20
|
+
store_expiry(conn, jid, @msg['at'])
|
|
21
|
+
return false if scheduled_jid
|
|
22
|
+
jid
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def store_expiry(conn, jid, time)
|
|
29
|
+
conn.set(debounce_key, jid)
|
|
30
|
+
conn.expireat(debounce_key, time.to_i)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def debounce_key
|
|
34
|
+
hash = Digest::MD5.hexdigest(@msg['args'].to_json)
|
|
35
|
+
@debounce_key ||= "sidekiq_debounce:#{@worker.name}:#{hash}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def scheduled_set
|
|
39
|
+
@scheduled_set ||= Sidekiq::ScheduledSet.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def reschedule(jid, at)
|
|
43
|
+
job = scheduled_set.find_job(jid)
|
|
44
|
+
job.reschedule(at)
|
|
45
|
+
jid
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def debounce?
|
|
49
|
+
(@msg['at'] && @worker.get_sidekiq_options['debounce']) || false
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'sidekiq/debounce/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'sidekiq-debounce'
|
|
8
|
+
spec.version = Sidekiq::Debounce::VERSION
|
|
9
|
+
spec.authors = ['Peter Lejeck']
|
|
10
|
+
spec.email = ['me@plejeck.com']
|
|
11
|
+
spec.summary = 'A client-side middleware for debouncing Sidekiq jobs'
|
|
12
|
+
spec.description = <<-DESC
|
|
13
|
+
Sidekiq::Debounce provides a way to rate-limit creation of Sidekiq jobs. When
|
|
14
|
+
you create a job on a Worker with debounce enabled, Sidekiq::Debounce will
|
|
15
|
+
delay the job until the debounce period has elapsed with no additional debounce
|
|
16
|
+
calls. If you make another job with the same arguments before the specified
|
|
17
|
+
time has elapsed, the timer is reset and the entire period must pass again
|
|
18
|
+
before the job is executed.
|
|
19
|
+
DESC
|
|
20
|
+
spec.homepage = 'https://github.com/NuckChorris/sidekiq-debounce'
|
|
21
|
+
spec.license = 'MIT'
|
|
22
|
+
|
|
23
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
24
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
25
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
|
26
|
+
spec.require_paths = ['lib']
|
|
27
|
+
|
|
28
|
+
spec.add_dependency 'sidekiq', '>= 3.0'
|
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
|
31
|
+
spec.add_development_dependency 'mock_redis'
|
|
32
|
+
spec.add_development_dependency 'mocha'
|
|
33
|
+
spec.add_development_dependency 'codeclimate-test-reporter'
|
|
34
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'sidekiq/api'
|
|
3
|
+
require 'sidekiq/debounce/middleware'
|
|
4
|
+
|
|
5
|
+
class DebouncedWorker
|
|
6
|
+
include Sidekiq::Worker
|
|
7
|
+
|
|
8
|
+
sidekiq_options debounce: true
|
|
9
|
+
|
|
10
|
+
def perform(_a, _b); end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe Sidekiq::Debounce do
|
|
14
|
+
before do
|
|
15
|
+
stub_scheduled_set
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
after do
|
|
19
|
+
Sidekiq.redis(&:flushdb)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:set) { Sidekiq::ScheduledSet.new }
|
|
23
|
+
let(:sorted_entry) { Sidekiq::SortedEntry.new(set, 0, 'jid' => '54321') }
|
|
24
|
+
|
|
25
|
+
it 'queues a job normally at first' do
|
|
26
|
+
DebouncedWorker.perform_in(60, 'foo', 'bar')
|
|
27
|
+
set.size.must_equal 1, 'set.size must be 1'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'ignores repeat jobs within the debounce time and reschedules' do
|
|
31
|
+
sorted_entry.expects(:reschedule)
|
|
32
|
+
|
|
33
|
+
DebouncedWorker.perform_in(60, 'foo', 'bar')
|
|
34
|
+
DebouncedWorker.perform_in(60, 'foo', 'bar')
|
|
35
|
+
set.size.must_equal 1, 'set.size must be 1'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'debounces jobs based on their arguments' do
|
|
39
|
+
DebouncedWorker.perform_in(60, 'boo', 'far')
|
|
40
|
+
DebouncedWorker.perform_in(60, 'foo', 'bar')
|
|
41
|
+
set.size.must_equal 2, 'set.size must be 2'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'creates the job immediately when given an instant job' do
|
|
45
|
+
DebouncedWorker.perform_async('foo', 'bar')
|
|
46
|
+
set.size.must_equal 0, 'set.size must be 0'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def stub_scheduled_set
|
|
50
|
+
set.stubs(:find_job).returns(sorted_entry)
|
|
51
|
+
Sidekiq::Debounce.any_instance.stubs(:scheduled_set).returns(set)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'sidekiq'
|
|
2
|
+
require 'sidekiq/testing'
|
|
3
|
+
require 'mock_redis'
|
|
4
|
+
|
|
5
|
+
# Disable Sidekiq's testing mocks and use MockRedis instead
|
|
6
|
+
Sidekiq::Testing.disable!
|
|
7
|
+
|
|
8
|
+
Sidekiq.configure_server do |config|
|
|
9
|
+
config.redis = ConnectionPool.new(size: 1) { MockRedis.new }
|
|
10
|
+
end
|
|
11
|
+
Sidekiq.configure_client do |config|
|
|
12
|
+
config.redis = ConnectionPool.new(size: 1) { MockRedis.new }
|
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: sidekiq-debounce
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Peter Lejeck
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-04-21 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: sidekiq
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '3.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bundler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.6'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.6'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: mock_redis
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: mocha
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: codeclimate-test-reporter
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
description: |
|
|
98
|
+
Sidekiq::Debounce provides a way to rate-limit creation of Sidekiq jobs. When
|
|
99
|
+
you create a job on a Worker with debounce enabled, Sidekiq::Debounce will
|
|
100
|
+
delay the job until the debounce period has elapsed with no additional debounce
|
|
101
|
+
calls. If you make another job with the same arguments before the specified
|
|
102
|
+
time has elapsed, the timer is reset and the entire period must pass again
|
|
103
|
+
before the job is executed.
|
|
104
|
+
email:
|
|
105
|
+
- me@plejeck.com
|
|
106
|
+
executables: []
|
|
107
|
+
extensions: []
|
|
108
|
+
extra_rdoc_files: []
|
|
109
|
+
files:
|
|
110
|
+
- ".editorconfig"
|
|
111
|
+
- ".gitignore"
|
|
112
|
+
- ".hound.yml"
|
|
113
|
+
- ".rubocop.yml"
|
|
114
|
+
- ".travis.yml"
|
|
115
|
+
- Gemfile
|
|
116
|
+
- LICENSE.txt
|
|
117
|
+
- README.md
|
|
118
|
+
- Rakefile
|
|
119
|
+
- lib/sidekiq/debounce.rb
|
|
120
|
+
- lib/sidekiq/debounce/version.rb
|
|
121
|
+
- sidekiq-debounce.gemspec
|
|
122
|
+
- spec/sidekiq/debounce_spec.rb
|
|
123
|
+
- spec/sidekiq_helper.rb
|
|
124
|
+
- spec/spec_helper.rb
|
|
125
|
+
homepage: https://github.com/NuckChorris/sidekiq-debounce
|
|
126
|
+
licenses:
|
|
127
|
+
- MIT
|
|
128
|
+
metadata: {}
|
|
129
|
+
post_install_message:
|
|
130
|
+
rdoc_options: []
|
|
131
|
+
require_paths:
|
|
132
|
+
- lib
|
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0'
|
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
|
+
requirements:
|
|
140
|
+
- - ">="
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: '0'
|
|
143
|
+
requirements: []
|
|
144
|
+
rubyforge_project:
|
|
145
|
+
rubygems_version: 2.2.2
|
|
146
|
+
signing_key:
|
|
147
|
+
specification_version: 4
|
|
148
|
+
summary: A client-side middleware for debouncing Sidekiq jobs
|
|
149
|
+
test_files:
|
|
150
|
+
- spec/sidekiq/debounce_spec.rb
|
|
151
|
+
- spec/sidekiq_helper.rb
|
|
152
|
+
- spec/spec_helper.rb
|