pause 0.1.2 → 0.2.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 +4 -4
- data/README.md +24 -0
- data/lib/pause/action.rb +5 -1
- data/lib/pause/analyzer.rb +7 -0
- data/lib/pause/configuration.rb +2 -2
- data/lib/pause/redis/adapter.rb +1 -1
- data/lib/pause/redis/sharded_adapter.rb +1 -1
- data/lib/pause/version.rb +1 -1
- data/spec/pause/action_spec.rb +51 -42
- data/spec/pause/analyzer_spec.rb +9 -8
- data/spec/pause/configuration_spec.rb +13 -10
- data/spec/pause/redis/adapter_spec.rb +20 -20
- data/spec/spec_helper.rb +0 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bda062b9f3c87e7079efe48798f512afc22cfad8
|
4
|
+
data.tar.gz: afcdfb3a35303d0a6dede0964e1d30c275553e50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d195486f30a502ef7fee7c77bbd0471f3eeea1622d207d81d4719126e94d4c5d3c8016176c9ff2a40f51f8ba947fda712b629eba702cce8b5819bec6430364f
|
7
|
+
data.tar.gz: c8af42cebe5703e60a2d484984f7ba1294d58ecdb9621911ebb02aca9ec66f2657cd0f3372f50c7d7cc8609e3ee92be91df778c2dcdde150760f80abec32833f
|
data/README.md
CHANGED
@@ -198,6 +198,30 @@ action.ok?
|
|
198
198
|
# => true
|
199
199
|
```
|
200
200
|
|
201
|
+
## Using Pause with Twemproxy
|
202
|
+
|
203
|
+
Pause can be used with Twemproxy to shard its data among multiple redis instances. When doing so,
|
204
|
+
the `hash_tag` configuration in Twemproxy should be set to `"||"`. In addition, the `sharded` Pause
|
205
|
+
configuration option should be set to true.
|
206
|
+
|
207
|
+
When sharding is used, the Redis adapter used by Pause ignores the `redis_db`, which is not supported.
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
Pause.configure do |config|
|
211
|
+
config.redis_host = "127.0.0.1"
|
212
|
+
config.redis_port = 6379
|
213
|
+
config.resolution = 600 # aggregate all events into 10 minute blocks
|
214
|
+
config.history = 86400 # discard all events older than 1 day
|
215
|
+
config.sharded = true
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
With this configuration, any Pause operation that we know is not supported by Twemproxy will raise
|
220
|
+
`Pause::Redis::OperationNotSupported`. For instance, when sharding we are unable to get a list of all
|
221
|
+
tracked identifiers.
|
222
|
+
|
223
|
+
The action block list is implemented as a sorted set, so it should still be usable when sharding.
|
224
|
+
|
201
225
|
## Contributing
|
202
226
|
|
203
227
|
Want to make it better? Cool. Here's how:
|
data/lib/pause/action.rb
CHANGED
@@ -14,7 +14,7 @@ module Pause
|
|
14
14
|
# end
|
15
15
|
#
|
16
16
|
def scope
|
17
|
-
raise
|
17
|
+
raise 'Should implement scope. (Ex: ipn:follow)'
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.scope(scope_identifier = nil)
|
@@ -57,6 +57,10 @@ module Pause
|
|
57
57
|
@checks = period_checks
|
58
58
|
end
|
59
59
|
|
60
|
+
def block_for(ttl)
|
61
|
+
adapter.rate_limit!(scope, identifier, ttl)
|
62
|
+
end
|
63
|
+
|
60
64
|
def increment!(count = 1, timestamp = Time.now.to_i)
|
61
65
|
adapter.increment(scope, identifier, timestamp, count)
|
62
66
|
end
|
data/lib/pause/analyzer.rb
CHANGED
@@ -4,7 +4,14 @@ module Pause
|
|
4
4
|
class Analyzer
|
5
5
|
include Pause::Helper::Timing
|
6
6
|
|
7
|
+
# #check(action)
|
8
|
+
#
|
9
|
+
# @param action [Pause::Action]
|
10
|
+
# @return [nil] everything is fine
|
11
|
+
# @return [false] this action is already blocked
|
12
|
+
# @return [Pause::RateLimitedEvent] the action was blocked as a result of this check
|
7
13
|
def check(action)
|
14
|
+
return false if adapter.rate_limited?(action.scope, action.identifier)
|
8
15
|
timestamp = period_marker(Pause.config.resolution, Time.now.to_i)
|
9
16
|
set = adapter.key_history(action.scope, action.identifier)
|
10
17
|
action.checks.each do |period_check|
|
data/lib/pause/configuration.rb
CHANGED
data/lib/pause/redis/adapter.rb
CHANGED
@@ -28,7 +28,7 @@ module Pause
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def keys(_key_scope)
|
31
|
-
raise OperationNotSupported.new(
|
31
|
+
raise OperationNotSupported.new('Can not be executed when Pause is configured in sharded mode')
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
data/lib/pause/version.rb
CHANGED
data/spec/pause/action_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Pause::Action do
|
|
5
5
|
include Pause::Helper::Timing
|
6
6
|
|
7
7
|
class MyNotification < Pause::Action
|
8
|
-
scope
|
8
|
+
scope 'ipn:follow'
|
9
9
|
check period_seconds: 20, max_allowed: 5, block_ttl: 40
|
10
10
|
check period_seconds: 40, max_allowed: 7, block_ttl: 40
|
11
11
|
end
|
@@ -13,19 +13,20 @@ describe Pause::Action do
|
|
13
13
|
let(:resolution) { 10 }
|
14
14
|
let(:history) { 60 }
|
15
15
|
let(:configuration) { Pause::Configuration.new }
|
16
|
+
let(:adapter) { Pause::Redis::Adapter.new(Pause.config) }
|
16
17
|
|
17
18
|
before do
|
18
19
|
allow(Pause).to receive(:config).and_return(configuration)
|
19
20
|
allow(Pause.config).to receive(:resolution).and_return(resolution)
|
20
21
|
allow(Pause.config).to receive(:history).and_return(history)
|
21
|
-
allow(Pause).to receive(:adapter).and_return(
|
22
|
+
allow(Pause).to receive(:adapter).and_return(adapter)
|
22
23
|
end
|
23
24
|
|
24
|
-
let(:action) { MyNotification.new(
|
25
|
-
let(:other_action) { MyNotification.new(
|
25
|
+
let(:action) { MyNotification.new('1237612') }
|
26
|
+
let(:other_action) { MyNotification.new('1237613') }
|
26
27
|
|
27
|
-
describe
|
28
|
-
it
|
28
|
+
describe '#increment!' do
|
29
|
+
it 'should increment' do
|
29
30
|
time = Time.now
|
30
31
|
Timecop.freeze time do
|
31
32
|
expect(Pause.adapter).to receive(:increment).with(action.scope, '1237612', time.to_i, 1)
|
@@ -34,8 +35,8 @@ describe Pause::Action do
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
|
-
describe
|
38
|
-
it
|
38
|
+
describe '#ok?' do
|
39
|
+
it 'should successfully return if the action is blocked or not' do
|
39
40
|
time = Time.now
|
40
41
|
Timecop.freeze time do
|
41
42
|
4.times do
|
@@ -47,7 +48,7 @@ describe Pause::Action do
|
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
it
|
51
|
+
it 'should successfully consider different period checks' do
|
51
52
|
time = Time.parse('Sept 22, 11:34:00')
|
52
53
|
|
53
54
|
Timecop.freeze time - 30 do
|
@@ -66,7 +67,7 @@ describe Pause::Action do
|
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
69
|
-
it
|
70
|
+
it 'should return false and silently fail if redis is not available' do
|
70
71
|
allow(Pause::Logger).to receive(:fatal)
|
71
72
|
allow_any_instance_of(Redis).to receive(:zrange).and_raise Redis::CannotConnectError
|
72
73
|
time = period_marker(resolution, Time.now.to_i)
|
@@ -77,15 +78,15 @@ describe Pause::Action do
|
|
77
78
|
end
|
78
79
|
end
|
79
80
|
|
80
|
-
describe
|
81
|
-
context
|
82
|
-
it
|
81
|
+
describe '#analyze' do
|
82
|
+
context 'action should not be rate limited' do
|
83
|
+
it 'returns nil' do
|
83
84
|
expect(action.analyze).to be nil
|
84
85
|
end
|
85
86
|
end
|
86
87
|
|
87
|
-
context
|
88
|
-
it
|
88
|
+
context 'action should be rate limited' do
|
89
|
+
it 'returns a RateLimitedEvent object' do
|
89
90
|
time = Time.now
|
90
91
|
rate_limit = nil
|
91
92
|
|
@@ -105,8 +106,8 @@ describe Pause::Action do
|
|
105
106
|
end
|
106
107
|
end
|
107
108
|
|
108
|
-
describe
|
109
|
-
it
|
109
|
+
describe '.tracked_identifiers' do
|
110
|
+
it 'should return all the identifiers tracked (but not blocked) so far' do
|
110
111
|
action.increment!
|
111
112
|
other_action.increment!
|
112
113
|
|
@@ -118,8 +119,8 @@ describe Pause::Action do
|
|
118
119
|
end
|
119
120
|
end
|
120
121
|
|
121
|
-
describe
|
122
|
-
it
|
122
|
+
describe '.rate_limited_identifiers' do
|
123
|
+
it 'should return all the identifiers blocked' do
|
123
124
|
action.increment!(100, Time.now.to_i)
|
124
125
|
other_action.increment!(100, Time.now.to_i)
|
125
126
|
|
@@ -131,8 +132,8 @@ describe Pause::Action do
|
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
134
|
-
describe
|
135
|
-
it
|
135
|
+
describe '.unblock_all' do
|
136
|
+
it 'should unblock all the identifiers for a scope' do
|
136
137
|
10.times { action.increment! }
|
137
138
|
other_action.increment!
|
138
139
|
|
@@ -149,7 +150,7 @@ describe Pause::Action do
|
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
152
|
-
describe
|
153
|
+
describe '#unblock' do
|
153
154
|
it 'unblocks the specified id' do
|
154
155
|
10.times { action.increment! }
|
155
156
|
|
@@ -160,9 +161,17 @@ describe Pause::Action do
|
|
160
161
|
expect(action.ok?).to be true
|
161
162
|
end
|
162
163
|
end
|
164
|
+
|
165
|
+
describe '#block_for' do
|
166
|
+
it 'blocks the IP for N seconds' do
|
167
|
+
expect(adapter).to receive(:rate_limit!).with(action.scope, action.identifier, 10).and_call_original
|
168
|
+
action.block_for(10)
|
169
|
+
expect(action.ok?).to be false
|
170
|
+
end
|
171
|
+
end
|
163
172
|
end
|
164
173
|
|
165
|
-
describe Pause::Action,
|
174
|
+
describe Pause::Action, '.check' do
|
166
175
|
class ActionWithCheck < Pause::Action
|
167
176
|
check 100, 150, 200
|
168
177
|
end
|
@@ -177,50 +186,50 @@ describe Pause::Action, ".check" do
|
|
177
186
|
check period_seconds: 50, block_ttl: 60, max_allowed: 100
|
178
187
|
end
|
179
188
|
|
180
|
-
it
|
181
|
-
expect(ActionWithCheck.new(
|
189
|
+
it 'should define a period check on new instances' do
|
190
|
+
expect(ActionWithCheck.new('id').checks).to eq([
|
182
191
|
Pause::PeriodCheck.new(100, 150, 200)
|
183
192
|
])
|
184
193
|
end
|
185
194
|
|
186
|
-
it
|
187
|
-
expect(ActionWithMultipleChecks.new(
|
195
|
+
it 'should define a period check on new instances' do
|
196
|
+
expect(ActionWithMultipleChecks.new('id').checks).to eq([
|
188
197
|
Pause::PeriodCheck.new(100, 150, 200),
|
189
198
|
Pause::PeriodCheck.new(200, 150, 200),
|
190
199
|
Pause::PeriodCheck.new(300, 150, 200)
|
191
200
|
])
|
192
201
|
end
|
193
202
|
|
194
|
-
it
|
195
|
-
expect(ActionWithHashChecks.new(
|
203
|
+
it 'should accept hash arguments' do
|
204
|
+
expect(ActionWithHashChecks.new('id').checks).to eq([
|
196
205
|
Pause::PeriodCheck.new(50, 100, 60)
|
197
206
|
])
|
198
207
|
end
|
199
208
|
|
200
209
|
end
|
201
210
|
|
202
|
-
describe Pause::Action,
|
211
|
+
describe Pause::Action, '.scope' do
|
203
212
|
class UndefinedScopeAction < Pause::Action
|
204
213
|
end
|
205
214
|
|
206
|
-
it
|
215
|
+
it 'should raise if scope is not defined' do
|
207
216
|
expect {
|
208
|
-
UndefinedScopeAction.new(
|
209
|
-
}.to raise_error(
|
217
|
+
UndefinedScopeAction.new('1.2.3.4').scope
|
218
|
+
}.to raise_error('Should implement scope. (Ex: ipn:follow)')
|
210
219
|
end
|
211
220
|
|
212
221
|
class DefinedScopeAction < Pause::Action
|
213
|
-
scope
|
222
|
+
scope 'my:scope'
|
214
223
|
end
|
215
224
|
|
216
|
-
it
|
217
|
-
expect(DefinedScopeAction.new(
|
225
|
+
it 'should set scope on class' do
|
226
|
+
expect(DefinedScopeAction.new('1.2.3.4').scope).to eq('my:scope')
|
218
227
|
end
|
219
228
|
end
|
220
229
|
|
221
|
-
describe Pause::Action,
|
230
|
+
describe Pause::Action, 'enabled/disabled states' do
|
222
231
|
class BlockedAction < Pause::Action
|
223
|
-
scope
|
232
|
+
scope 'blocked'
|
224
233
|
check 10, 0, 10
|
225
234
|
end
|
226
235
|
|
@@ -233,27 +242,27 @@ describe Pause::Action, "enabled/disabled states" do
|
|
233
242
|
|
234
243
|
let(:action) { BlockedAction }
|
235
244
|
|
236
|
-
describe
|
245
|
+
describe '#disable' do
|
237
246
|
before do
|
238
247
|
expect(action).to be_enabled
|
239
248
|
expect(action).to_not be_disabled
|
240
249
|
action.disable
|
241
250
|
end
|
242
251
|
|
243
|
-
it
|
252
|
+
it 'disables the action' do
|
244
253
|
expect(action).to be_disabled
|
245
254
|
expect(action).to_not be_enabled
|
246
255
|
end
|
247
256
|
end
|
248
257
|
|
249
|
-
describe
|
258
|
+
describe '#enable' do
|
250
259
|
before do
|
251
260
|
action.disable
|
252
261
|
expect(action).to_not be_enabled
|
253
262
|
action.enable
|
254
263
|
end
|
255
264
|
|
256
|
-
it
|
265
|
+
it 'enables the action' do
|
257
266
|
expect(action).to be_enabled
|
258
267
|
expect(action).to_not be_disabled
|
259
268
|
end
|
data/spec/pause/analyzer_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Pause::Analyzer do
|
|
5
5
|
include Pause::Helper::Timing
|
6
6
|
|
7
7
|
class FollowPushNotification < Pause::Action
|
8
|
-
scope
|
8
|
+
scope 'ipn:follow'
|
9
9
|
check 20, 5, 12
|
10
10
|
check 40, 7, 12
|
11
11
|
end
|
@@ -13,19 +13,20 @@ describe Pause::Analyzer do
|
|
13
13
|
let(:resolution) { 10 }
|
14
14
|
let(:history) { 60 }
|
15
15
|
let(:configuration) { Pause::Configuration.new }
|
16
|
+
let(:adapter) { Pause::Redis::Adapter.new(configuration) }
|
16
17
|
|
17
18
|
before do
|
18
19
|
allow(Pause).to receive(:config).and_return(configuration)
|
19
20
|
allow(Pause.config).to receive(:resolution).and_return(resolution)
|
20
21
|
allow(Pause.config).to receive(:history).and_return(history)
|
22
|
+
allow(Pause).to receive(:adapter).and_return(adapter)
|
21
23
|
end
|
22
24
|
|
23
25
|
let(:analyzer) { Pause.analyzer }
|
24
|
-
let(:
|
25
|
-
let(:action) { FollowPushNotification.new("1243123") }
|
26
|
+
let(:action) { FollowPushNotification.new('1243123') }
|
26
27
|
|
27
|
-
describe
|
28
|
-
it
|
28
|
+
describe '#analyze' do
|
29
|
+
it 'checks and blocks if max_allowed is reached' do
|
29
30
|
time = Time.now
|
30
31
|
expect(adapter).to receive(:rate_limit!).once.with(action.scope, '1243123', 12)
|
31
32
|
Timecop.freeze time do
|
@@ -37,12 +38,12 @@ describe Pause::Analyzer do
|
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
describe
|
41
|
-
it
|
41
|
+
describe '#check' do
|
42
|
+
it 'should return nil if action is NOT blocked' do
|
42
43
|
expect(analyzer.check(action)).to be nil
|
43
44
|
end
|
44
45
|
|
45
|
-
it
|
46
|
+
it 'should return blocked action if action is blocked' do
|
46
47
|
Timecop.freeze Time.now do
|
47
48
|
5.times do
|
48
49
|
action.increment!
|
@@ -1,36 +1,39 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Pause::Configuration,
|
3
|
+
describe Pause::Configuration, '#configure' do
|
4
4
|
|
5
5
|
subject { Pause::Configuration.new }
|
6
6
|
|
7
|
-
it
|
7
|
+
it 'should allow configuration via block' do
|
8
8
|
subject.configure do |c|
|
9
|
-
c.redis_host =
|
10
|
-
c.redis_port =
|
11
|
-
c.redis_db =
|
9
|
+
c.redis_host = '128.23.12.8'
|
10
|
+
c.redis_port = '2134'
|
11
|
+
c.redis_db = '13'
|
12
12
|
|
13
13
|
c.resolution = 5000
|
14
14
|
c.history = 6000
|
15
|
+
c.sharded = true
|
15
16
|
end
|
16
17
|
|
17
|
-
expect(subject.redis_host).to eq(
|
18
|
+
expect(subject.redis_host).to eq('128.23.12.8')
|
18
19
|
expect(subject.redis_port).to eq(2134)
|
19
|
-
expect(subject.redis_db).to eq(
|
20
|
+
expect(subject.redis_db).to eq('13')
|
20
21
|
|
21
22
|
expect(subject.resolution).to eq(5000)
|
22
23
|
expect(subject.history).to eq(6000)
|
24
|
+
expect(subject.sharded).to be true
|
23
25
|
end
|
24
26
|
|
25
|
-
it
|
27
|
+
it 'should provide redis defaults' do
|
26
28
|
subject.configure do |config|
|
27
29
|
# do nothing
|
28
30
|
end
|
29
31
|
|
30
|
-
expect(subject.redis_host).to eq(
|
32
|
+
expect(subject.redis_host).to eq('127.0.0.1')
|
31
33
|
expect(subject.redis_port).to eq(6379)
|
32
|
-
expect(subject.redis_db).to eq(
|
34
|
+
expect(subject.redis_db).to eq('1')
|
33
35
|
expect(subject.resolution).to eq(600) # 10 minutes
|
34
36
|
expect(subject.history).to eq(86400) # one day
|
37
|
+
expect(subject.sharded).to be false
|
35
38
|
end
|
36
39
|
end
|
@@ -19,11 +19,11 @@ describe Pause::Redis::Adapter do
|
|
19
19
|
let(:redis_conn) { adapter.send(:redis) }
|
20
20
|
|
21
21
|
describe '#increment' do
|
22
|
-
let(:scope) {
|
23
|
-
let(:identifier) {
|
24
|
-
let(:tracked_key) {
|
22
|
+
let(:scope) { 'blah' }
|
23
|
+
let(:identifier) { '213213' }
|
24
|
+
let(:tracked_key) { 'i:blah:|213213|' }
|
25
25
|
|
26
|
-
it
|
26
|
+
it 'should add key to a redis set' do
|
27
27
|
adapter.increment(scope, identifier, Time.now.to_i)
|
28
28
|
set = redis_conn.zrange(tracked_key, 0, -1, :with_scores => true)
|
29
29
|
expect(set).to_not be_empty
|
@@ -31,7 +31,7 @@ describe Pause::Redis::Adapter do
|
|
31
31
|
expect(set[0].size).to eql(2)
|
32
32
|
end
|
33
33
|
|
34
|
-
it
|
34
|
+
it 'should remove old key from a redis set' do
|
35
35
|
time = Time.now
|
36
36
|
expect(redis_conn).to receive(:zrem).with(tracked_key, [adapter.period_marker(resolution, time)])
|
37
37
|
|
@@ -44,7 +44,7 @@ describe Pause::Redis::Adapter do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
it
|
47
|
+
it 'sets expiry on key' do
|
48
48
|
expect(redis_conn).to receive(:expire).with(tracked_key, history)
|
49
49
|
adapter.increment(scope, identifier, Time.now.to_i)
|
50
50
|
end
|
@@ -73,41 +73,41 @@ describe Pause::Redis::Adapter do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
describe
|
76
|
+
describe '#rate_limit!' do
|
77
77
|
end
|
78
78
|
|
79
|
-
describe
|
79
|
+
describe '#rate_limited?' do
|
80
80
|
let(:scope) { 'ipn:follow' }
|
81
81
|
let(:identifier) { '123461234' }
|
82
82
|
let(:blocked_key) { "b:#{key}" }
|
83
83
|
let(:ttl) { 110000 }
|
84
84
|
|
85
|
-
it
|
85
|
+
it 'should return true if blocked' do
|
86
86
|
adapter.rate_limit!(scope, identifier, ttl)
|
87
87
|
expect(adapter.rate_limited?(scope, identifier)).to be true
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
describe
|
92
|
-
it
|
93
|
-
expect(adapter.send(:tracked_key,
|
91
|
+
describe '#tracked_key' do
|
92
|
+
it 'prefixes key' do
|
93
|
+
expect(adapter.send(:tracked_key, 'abc', '12345')).to eq('i:abc:|12345|')
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
97
|
describe '#enable' do
|
98
98
|
it 'deletes the disabled flag in redis' do
|
99
|
-
adapter.disable(
|
100
|
-
expect(adapter.disabled?(
|
101
|
-
adapter.enable(
|
102
|
-
expect(adapter.disabled?(
|
99
|
+
adapter.disable('boom')
|
100
|
+
expect(adapter.disabled?('boom')).to be true
|
101
|
+
adapter.enable('boom')
|
102
|
+
expect(adapter.disabled?('boom')).to be false
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
106
|
describe '#disable' do
|
107
107
|
it 'sets the disabled flag in redis' do
|
108
|
-
expect(adapter.enabled?(
|
109
|
-
adapter.disable(
|
110
|
-
expect(adapter.enabled?(
|
108
|
+
expect(adapter.enabled?('boom')).to be true
|
109
|
+
adapter.disable('boom')
|
110
|
+
expect(adapter.enabled?('boom')).to be false
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -124,7 +124,7 @@ describe Pause::Redis::Adapter do
|
|
124
124
|
let(:blocked_key) { "b:|#{scope}|" }
|
125
125
|
let(:ttl) { 110000 }
|
126
126
|
|
127
|
-
it
|
127
|
+
it 'saves ip to redis with expiration' do
|
128
128
|
time = Time.now
|
129
129
|
Timecop.freeze time do
|
130
130
|
adapter.rate_limit!(scope, identifier, ttl)
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pause
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Atasay Gokkaya
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-
|
14
|
+
date: 2015-11-07 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: redis
|
@@ -85,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
85
|
version: '0'
|
86
86
|
requirements: []
|
87
87
|
rubyforge_project:
|
88
|
-
rubygems_version: 2.2.
|
88
|
+
rubygems_version: 2.2.2
|
89
89
|
signing_key:
|
90
90
|
specification_version: 4
|
91
91
|
summary: RReal time rate limiting for multi-process ruby environments based on Redis
|