pause 0.0.5 → 0.0.6

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
+ 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: