pause 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cebe59883ec6e4803896b89e61d88c53f43902cc
4
+ data.tar.gz: 86067516015b359cbe2becb8d2e5b71748484f70
5
+ SHA512:
6
+ metadata.gz: 3538a2c610971934961be482f4531e43a1b614c4d48786484592f4e9c170ef5e4694055d1e8efb80839c62d636c93f997907fd5c9ed1df181adcf8bb6711d361
7
+ data.tar.gz: bb3921bf9935e98176a073ac2dabcf43c1786c75ce5e532b04497dba4a8dff039d28ed9a1f88b12fd9a5da6052259e762e1cba1a66bd87bf7288f7d771021e42
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  Pause
2
2
  ======
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/pause.png)](http://badge.fury.io/rb/pause)
4
5
  [![Build status](https://secure.travis-ci.org/wanelo/pause.png)](http://travis-ci.org/wanelo/pause)
5
6
 
6
7
  Pause is a flexible Redis-backed rate-limiting client. Use it to track events, with
@@ -173,6 +174,29 @@ while true
173
174
  end
174
175
  ```
175
176
 
177
+ ## Unblocking
178
+
179
+ Actions can be unblocked manually after they have been blocked.
180
+
181
+ To unblock all blocked identifiers for a single action:
182
+
183
+ ```ruby
184
+ MyAction.unblock_all
185
+ ```
186
+
187
+ To unblock a single identifier for an action:
188
+
189
+ ```ruby
190
+ action = MyAction.new('hello')
191
+
192
+ action.ok?
193
+ # => false
194
+
195
+ action.unblock
196
+
197
+ action.ok?
198
+ # => true
199
+ ```
176
200
 
177
201
  ## Contributing
178
202
 
@@ -24,6 +24,10 @@ module Pause
24
24
  @analyzer ||= Pause::Analyzer.new
25
25
  end
26
26
 
27
+ def adapter
28
+ @adapter ||= Pause::Redis::Adapter.new(config)
29
+ end
30
+
27
31
  def configure(&block)
28
32
  @configuration = Pause::Configuration.new.configure(&block)
29
33
  end
@@ -50,7 +50,7 @@ module Pause
50
50
  end
51
51
 
52
52
  def checks
53
- self.class.instance_variable_get(:@checks)
53
+ self.class.checks
54
54
  end
55
55
 
56
56
  def self.checks=(period_checks)
@@ -58,7 +58,7 @@ module Pause
58
58
  end
59
59
 
60
60
  def increment!(count = 1, timestamp = Time.now.to_i)
61
- Pause.analyzer.increment(self, timestamp, count)
61
+ adapter.increment(key, timestamp, count)
62
62
  end
63
63
 
64
64
  def rate_limited?
@@ -77,19 +77,23 @@ module Pause
77
77
  end
78
78
 
79
79
  def self.tracked_identifiers
80
- Pause.analyzer.tracked_identifiers(self.class_scope)
80
+ adapter.all_keys(self.class_scope)
81
81
  end
82
82
 
83
83
  def self.rate_limited_identifiers
84
- Pause.analyzer.rate_limited_identifiers(self.class_scope)
84
+ adapter.rate_limited_keys(self.class_scope)
85
85
  end
86
86
 
87
87
  def self.unblock_all
88
- Pause.analyzer.adapter.delete_rate_limited_keys(self.class_scope)
88
+ adapter.delete_rate_limited_keys(self.class_scope)
89
+ end
90
+
91
+ def unblock
92
+ adapter.delete_rate_limited_key(scope, identifier)
89
93
  end
90
94
 
91
95
  def key
92
- "#{self.scope}:#{@identifier}"
96
+ "#{self.scope}:#{identifier}"
93
97
  end
94
98
 
95
99
  # Actions can be globally disabled or re-enabled in a persistent
@@ -104,15 +108,15 @@ module Pause
104
108
  # MyAction.disabled? => false
105
109
  #
106
110
  def self.enable
107
- Pause.analyzer.adapter.enable(class_scope)
111
+ adapter.enable(class_scope)
108
112
  end
109
113
 
110
114
  def self.disable
111
- Pause.analyzer.adapter.disable(class_scope)
115
+ adapter.disable(class_scope)
112
116
  end
113
117
 
114
118
  def self.enabled?
115
- Pause.analyzer.adapter.enabled?(class_scope)
119
+ adapter.enabled?(class_scope)
116
120
  end
117
121
 
118
122
  def self.disabled?
@@ -121,6 +125,14 @@ module Pause
121
125
 
122
126
  private
123
127
 
128
+ def self.adapter
129
+ Pause.adapter
130
+ end
131
+
132
+ def adapter
133
+ self.class.adapter
134
+ end
135
+
124
136
  def self.class_scope
125
137
  class_variable_get:@@class_scope if class_variable_defined?(:@@class_scope)
126
138
  end
@@ -4,31 +4,7 @@ module Pause
4
4
  class Analyzer
5
5
  include Pause::Helper::Timing
6
6
 
7
- attr_accessor :adapter
8
-
9
- def initialize
10
- @adapter ||= Pause::Redis::Adapter.new(Pause.config)
11
- end
12
-
13
- def increment(action, timestamp = Time.now.to_i, count = 1)
14
- adapter.increment(action.key, timestamp, count)
15
- end
16
-
17
7
  def check(action)
18
- analyze(action)
19
- end
20
-
21
- def tracked_identifiers(scope)
22
- adapter.all_keys(scope)
23
- end
24
-
25
- def rate_limited_identifiers(scope)
26
- adapter.rate_limited_keys(scope)
27
- end
28
-
29
- private
30
-
31
- def analyze(action)
32
8
  timestamp = period_marker(Pause.config.resolution, Time.now.to_i)
33
9
  set = adapter.key_history(action.key)
34
10
  action.checks.each do |period_check|
@@ -48,5 +24,10 @@ module Pause
48
24
  nil
49
25
  end
50
26
 
27
+ private
28
+
29
+ def adapter
30
+ Pause.adapter
31
+ end
51
32
  end
52
33
  end
@@ -50,10 +50,11 @@ module Pause
50
50
  end
51
51
 
52
52
  def delete_rate_limited_keys(scope)
53
- ids = rate_limited_keys(scope)
54
- increment_keys = ids.map{ |key| white_key(scope, key) }
55
- rate_limited_keys = ids.map{ |key| rate_limited_key(scope, key) }
56
- redis.del (increment_keys + rate_limited_keys)
53
+ delete_rate_limited_ids scope, rate_limited_keys(scope)
54
+ end
55
+
56
+ def delete_rate_limited_key(scope, id)
57
+ delete_rate_limited_ids scope, [id]
57
58
  end
58
59
 
59
60
  def disable(scope)
@@ -74,6 +75,12 @@ module Pause
74
75
 
75
76
  private
76
77
 
78
+ def delete_rate_limited_ids(scope, ids)
79
+ increment_keys = ids.map{ |key| white_key(scope, key) }
80
+ rate_limited_keys = ids.map{ |key| rate_limited_key(scope, key) }
81
+ redis.del(increment_keys + rate_limited_keys)
82
+ end
83
+
77
84
  def redis
78
85
  @redis_conn ||= ::Redis.new(host: Pause.config.redis_host,
79
86
  port: Pause.config.redis_port,
@@ -1,3 +1,3 @@
1
1
  module Pause
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -27,7 +27,7 @@ describe Pause::Action do
27
27
  it "should increment" do
28
28
  time = Time.now
29
29
  Timecop.freeze time do
30
- Pause.analyzer.should_receive(:increment).with(action, time.to_i, 1)
30
+ Pause.adapter.should_receive(:increment).with(action.key, time.to_i, 1)
31
31
  action.increment!
32
32
  end
33
33
  end
@@ -58,7 +58,6 @@ describe Pause::Action do
58
58
  action.increment! 1, time
59
59
 
60
60
  action.ok?.should be_false
61
-
62
61
  end
63
62
 
64
63
  it "should return false and silently fail if redis is not available" do
@@ -99,7 +98,7 @@ describe Pause::Action do
99
98
  end
100
99
  end
101
100
 
102
- describe "#tracked_identifiers" do
101
+ describe ".tracked_identifiers" do
103
102
  it "should return all the identifiers tracked (but not blocked) so far" do
104
103
  action.increment!
105
104
  other_action.increment!
@@ -112,7 +111,7 @@ describe Pause::Action do
112
111
  end
113
112
  end
114
113
 
115
- describe "#rate_limited_identifiers" do
114
+ describe ".rate_limited_identifiers" do
116
115
  it "should return all the identifiers blocked" do
117
116
  action.increment!(100, Time.now.to_i)
118
117
  other_action.increment!(100, Time.now.to_i)
@@ -125,7 +124,7 @@ describe Pause::Action do
125
124
  end
126
125
  end
127
126
 
128
- describe "#unblock_all" do
127
+ describe ".unblock_all" do
129
128
  it "should unblock all the identifiers for a scope" do
130
129
  10.times { action.increment! }
131
130
  other_action.increment!
@@ -142,6 +141,18 @@ describe Pause::Action do
142
141
  MyNotification.tracked_identifiers.should == [other_action.identifier]
143
142
  end
144
143
  end
144
+
145
+ describe "#unblock" do
146
+ it 'unblocks the specified id' do
147
+ 10.times { action.increment! }
148
+
149
+ expect(action.ok?).to be_false
150
+
151
+ action.unblock
152
+
153
+ expect(action.ok?).to be_true
154
+ end
155
+ end
145
156
  end
146
157
 
147
158
  describe Pause::Action, ".check" do
@@ -21,26 +21,16 @@ describe Pause::Analyzer do
21
21
  end
22
22
 
23
23
  let(:analyzer) { Pause.analyzer }
24
- let(:adapter) { Pause.analyzer.adapter }
24
+ let(:adapter) { Pause.adapter }
25
25
  let(:action) { FollowPushNotification.new("1243123") }
26
26
 
27
- describe "#increment" do
28
- it "should increment an action" do
29
- time = Time.now
30
- adapter.should_receive(:increment).with(action.key, time.to_i, 1)
31
- Timecop.freeze time do
32
- analyzer.increment(action)
33
- end
34
- end
35
- end
36
-
37
27
  describe "#analyze" do
38
28
  it "checks and blocks if max_allowed is reached" do
39
29
  time = Time.now
40
30
  adapter.should_receive(:rate_limit!).once.with(action.key, 12)
41
31
  Timecop.freeze time do
42
32
  5.times do
43
- analyzer.increment(action)
33
+ action.increment!
44
34
  analyzer.check(action)
45
35
  end
46
36
  end
@@ -55,7 +45,7 @@ describe Pause::Analyzer do
55
45
  it "should return blocked action if action is blocked" do
56
46
  Timecop.freeze Time.now do
57
47
  5.times do
58
- analyzer.increment(action)
48
+ action.increment!
59
49
  end
60
50
  analyzer.check(action).should be_a(Pause::RateLimitedEvent)
61
51
  end
@@ -12,6 +12,7 @@ describe Pause::Redis::Adapter do
12
12
  Pause.stub(:config).and_return(configuration)
13
13
  Pause.config.stub(:resolution).and_return(resolution)
14
14
  Pause.config.stub(:history).and_return(history)
15
+ redis_conn.flushall
15
16
  end
16
17
 
17
18
  let(:adapter) { Pause::Redis::Adapter.new(Pause.config) }
@@ -75,4 +76,59 @@ describe Pause::Redis::Adapter do
75
76
  adapter.send(:white_key, "abc").should == "i:abc"
76
77
  end
77
78
  end
79
+
80
+ describe '#enable' do
81
+ it 'deletes the disabled flag in redis' do
82
+ adapter.disable("boom")
83
+ expect(adapter.disabled?("boom")).to be_true
84
+ adapter.enable("boom")
85
+ expect(adapter.disabled?("boom")).to be_false
86
+ end
87
+ end
88
+
89
+ describe '#disable' do
90
+ it 'sets the disabled flag in redis' do
91
+ expect(adapter.enabled?("boom")).to be_true
92
+ adapter.disable("boom")
93
+ expect(adapter.enabled?("boom")).to be_false
94
+ end
95
+ end
96
+
97
+ describe '#rate_limit!' do
98
+ it 'rate limits a key for a specific ttl' do
99
+ expect(adapter.rate_limited?('1')).to be_false
100
+ adapter.rate_limit!('1', 10)
101
+ expect(adapter.rate_limited?('1')).to be_true
102
+ end
103
+ end
104
+
105
+ describe '#delete_rate_limited_keys' do
106
+ it 'calls redis del with all keys' do
107
+ adapter.rate_limit!('boom:1', 10)
108
+ adapter.rate_limit!('boom:2', 10)
109
+
110
+ expect(adapter.rate_limited?('boom:1')).to be_true
111
+ expect(adapter.rate_limited?('boom:2')).to be_true
112
+
113
+ adapter.delete_rate_limited_keys('boom')
114
+
115
+ expect(adapter.rate_limited?('boom:1')).to be_false
116
+ expect(adapter.rate_limited?('boom:2')).to be_false
117
+ end
118
+ end
119
+
120
+ describe '#delete_rate_limit_key' do
121
+ it 'calls redis del with all keys' do
122
+ adapter.rate_limit!('boom:1', 10)
123
+ adapter.rate_limit!('boom:2', 10)
124
+
125
+ expect(adapter.rate_limited?('boom:1')).to be_true
126
+ expect(adapter.rate_limited?('boom:2')).to be_true
127
+
128
+ adapter.delete_rate_limited_key('boom', '1')
129
+
130
+ expect(adapter.rate_limited?('boom:1')).to be_false
131
+ expect(adapter.rate_limited?('boom:2')).to be_true
132
+ end
133
+ end
78
134
  end
@@ -21,4 +21,8 @@ RSpec.configure do |config|
21
21
  # the seed, which is printed after each run.
22
22
  # --seed 1234
23
23
  config.order = 'random'
24
+
25
+ config.before :each do
26
+ Redis.new.flushall
27
+ end
24
28
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pause
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
5
- prerelease:
4
+ version: 0.0.6
6
5
  platform: ruby
7
6
  authors:
8
7
  - Atasay Gokkaya
@@ -12,102 +11,90 @@ authors:
12
11
  autorequire:
13
12
  bindir: bin
14
13
  cert_chain: []
15
- date: 2012-11-26 00:00:00.000000000 Z
14
+ date: 2014-05-23 00:00:00.000000000 Z
16
15
  dependencies:
17
16
  - !ruby/object:Gem::Dependency
18
17
  name: redis
19
18
  requirement: !ruby/object:Gem::Requirement
20
- none: false
21
19
  requirements:
22
- - - ! '>='
20
+ - - ">="
23
21
  - !ruby/object:Gem::Version
24
22
  version: '0'
25
23
  type: :runtime
26
24
  prerelease: false
27
25
  version_requirements: !ruby/object:Gem::Requirement
28
- none: false
29
26
  requirements:
30
- - - ! '>='
27
+ - - ">="
31
28
  - !ruby/object:Gem::Version
32
29
  version: '0'
33
30
  - !ruby/object:Gem::Dependency
34
31
  name: rspec
35
32
  requirement: !ruby/object:Gem::Requirement
36
- none: false
37
33
  requirements:
38
- - - ! '>='
34
+ - - ">="
39
35
  - !ruby/object:Gem::Version
40
36
  version: '0'
41
37
  type: :development
42
38
  prerelease: false
43
39
  version_requirements: !ruby/object:Gem::Requirement
44
- none: false
45
40
  requirements:
46
- - - ! '>='
41
+ - - ">="
47
42
  - !ruby/object:Gem::Version
48
43
  version: '0'
49
44
  - !ruby/object:Gem::Dependency
50
45
  name: fakeredis
51
46
  requirement: !ruby/object:Gem::Requirement
52
- none: false
53
47
  requirements:
54
- - - ! '>='
48
+ - - ">="
55
49
  - !ruby/object:Gem::Version
56
50
  version: '0'
57
51
  type: :development
58
52
  prerelease: false
59
53
  version_requirements: !ruby/object:Gem::Requirement
60
- none: false
61
54
  requirements:
62
- - - ! '>='
55
+ - - ">="
63
56
  - !ruby/object:Gem::Version
64
57
  version: '0'
65
58
  - !ruby/object:Gem::Dependency
66
59
  name: timecop
67
60
  requirement: !ruby/object:Gem::Requirement
68
- none: false
69
61
  requirements:
70
- - - ! '>='
62
+ - - ">="
71
63
  - !ruby/object:Gem::Version
72
64
  version: '0'
73
65
  type: :development
74
66
  prerelease: false
75
67
  version_requirements: !ruby/object:Gem::Requirement
76
- none: false
77
68
  requirements:
78
- - - ! '>='
69
+ - - ">="
79
70
  - !ruby/object:Gem::Version
80
71
  version: '0'
81
72
  - !ruby/object:Gem::Dependency
82
73
  name: guard-rspec
83
74
  requirement: !ruby/object:Gem::Requirement
84
- none: false
85
75
  requirements:
86
- - - ! '>='
76
+ - - ">="
87
77
  - !ruby/object:Gem::Version
88
78
  version: '0'
89
79
  type: :development
90
80
  prerelease: false
91
81
  version_requirements: !ruby/object:Gem::Requirement
92
- none: false
93
82
  requirements:
94
- - - ! '>='
83
+ - - ">="
95
84
  - !ruby/object:Gem::Version
96
85
  version: '0'
97
86
  - !ruby/object:Gem::Dependency
98
87
  name: rb-fsevent
99
88
  requirement: !ruby/object:Gem::Requirement
100
- none: false
101
89
  requirements:
102
- - - ! '>='
90
+ - - ">="
103
91
  - !ruby/object:Gem::Version
104
92
  version: '0'
105
93
  type: :development
106
94
  prerelease: false
107
95
  version_requirements: !ruby/object:Gem::Requirement
108
- none: false
109
96
  requirements:
110
- - - ! '>='
97
+ - - ">="
111
98
  - !ruby/object:Gem::Version
112
99
  version: '0'
113
100
  description: Real time rate limiting for multi-process ruby environments based on
@@ -121,11 +108,11 @@ executables: []
121
108
  extensions: []
122
109
  extra_rdoc_files: []
123
110
  files:
124
- - .gitignore
125
- - .pairs
126
- - .rspec
127
- - .rvmrc
128
- - .travis.yml
111
+ - ".gitignore"
112
+ - ".pairs"
113
+ - ".rspec"
114
+ - ".rvmrc"
115
+ - ".travis.yml"
129
116
  - Gemfile
130
117
  - Guardfile
131
118
  - LICENSE.txt
@@ -148,27 +135,26 @@ files:
148
135
  - spec/support/fakeredis.rb
149
136
  homepage: https://github.com/wanelo/pause
150
137
  licenses: []
138
+ metadata: {}
151
139
  post_install_message:
152
140
  rdoc_options: []
153
141
  require_paths:
154
142
  - lib
155
143
  required_ruby_version: !ruby/object:Gem::Requirement
156
- none: false
157
144
  requirements:
158
- - - ! '>='
145
+ - - ">="
159
146
  - !ruby/object:Gem::Version
160
147
  version: '0'
161
148
  required_rubygems_version: !ruby/object:Gem::Requirement
162
- none: false
163
149
  requirements:
164
- - - ! '>='
150
+ - - ">="
165
151
  - !ruby/object:Gem::Version
166
152
  version: '0'
167
153
  requirements: []
168
154
  rubyforge_project:
169
- rubygems_version: 1.8.24
155
+ rubygems_version: 2.2.0
170
156
  signing_key:
171
- specification_version: 3
157
+ specification_version: 4
172
158
  summary: RReal time rate limiting for multi-process ruby environments based on Redis
173
159
  test_files:
174
160
  - spec/pause/action_spec.rb
@@ -177,3 +163,4 @@ test_files:
177
163
  - spec/pause/redis/adapter_spec.rb
178
164
  - spec/spec_helper.rb
179
165
  - spec/support/fakeredis.rb
166
+ has_rdoc: