Skip to content
This repository was archived by the owner on Dec 1, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc
coverage
Expand Down
67 changes: 67 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
PATH
remote: .
specs:
pause (0.0.6)
redis

GEM
remote: https://rubygems.org/
specs:
celluloid (0.15.2)
timers (~> 1.1.0)
coderay (1.1.0)
diff-lcs (1.2.5)
fakeredis (0.5.0)
redis (~> 3.0)
ffi (1.9.3)
formatador (0.2.5)
guard (2.6.1)
formatador (>= 0.2.4)
listen (~> 2.7)
lumberjack (~> 1.0)
pry (>= 0.9.12)
thor (>= 0.18.1)
guard-rspec (4.2.9)
guard (~> 2.1)
rspec (>= 2.14, < 4.0)
listen (2.7.5)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
lumberjack (1.0.5)
method_source (0.8.2)
pry (0.9.12.6)
coderay (~> 1.0)
method_source (~> 0.8)
slop (~> 3.4)
rb-fsevent (0.9.4)
rb-inotify (0.9.4)
ffi (>= 0.5.0)
redis (3.1.0)
rspec (3.0.0)
rspec-core (~> 3.0.0)
rspec-expectations (~> 3.0.0)
rspec-mocks (~> 3.0.0)
rspec-core (3.0.3)
rspec-support (~> 3.0.0)
rspec-expectations (3.0.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.0.0)
rspec-mocks (3.0.3)
rspec-support (~> 3.0.0)
rspec-support (3.0.3)
slop (3.5.0)
thor (0.19.1)
timecop (0.7.1)
timers (1.1.0)

PLATFORMS
ruby

DEPENDENCIES
fakeredis
guard-rspec
pause!
rb-fsevent
rspec (~> 3.0)
timecop
3 changes: 1 addition & 2 deletions lib/pause/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,8 @@ def rate_limited?
end

def ok?
Pause.analyzer.check(self).nil?
!Pause.adapter.rate_limited?(key) && Pause.analyzer.check(self).nil?
rescue ::Redis::CannotConnectError => e
$stderr.puts "Error connecting to redis: #{e.inspect}"
false
end

Expand Down
45 changes: 36 additions & 9 deletions lib/pause/analyzer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,57 @@ module Pause
class Analyzer
include Pause::Helper::Timing

def check(action)
timestamp = period_marker(Pause.config.resolution, Time.now.to_i)
set = adapter.key_history(action.key)
action.checks.each do |period_check|
class BlockTTLChecker < Struct.new(:period_check, :timestamp, :set, :action)
def check
start_time = timestamp - period_check.period_seconds
set.reverse.inject(0) do |sum, element|
break if element.ts < start_time
sum += element.count
if sum >= period_check.max_allowed
adapter.rate_limit!(action.key, period_check.block_ttl)
Pause.adapter.rate_limit!(action.key, period_check.block_ttl)
# Note that Time.now is different from period_marker(resolution, Time.now), which
# rounds down to the nearest (resolution) seconds
return Pause::RateLimitedEvent.new(action, period_check, sum, Time.now.to_i)
end
sum
end
nil
end
nil
end

private
class PeriodTTLChecker < Struct.new(:period_check, :timestamp, :set, :action)
def check
start_time = timestamp - period_check.period_seconds
set.select!{|element| element.ts >= start_time}
set.inject(0) do |sum, element|
sum += element.count
if sum >= period_check.max_allowed
block_ttl = set.first.ts + period_check.period_seconds - element.ts
Pause.adapter.rate_limit!(action.key, block_ttl)
# Note that Time.now is different from period_marker(resolution, Time.now), which
# rounds down to the nearest (resolution) seconds
return Pause::RateLimitedEvent.new(action, period_check, sum, Time.now.to_i)
end
sum
end
nil
end
end

def check(action)
timestamp = period_marker(Pause.config.resolution, Time.now.to_i)
set = Pause.adapter.key_history(action.key)
action.checks.each do |period_check|
checker = if period_check.block_ttl
BlockTTLChecker.new(period_check, timestamp, set, action)
else
PeriodTTLChecker.new(period_check, timestamp, set, action)
end

def adapter
Pause.adapter
result = checker.check
return result if result
end
nil
end
end
end
2 changes: 1 addition & 1 deletion pause.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Gem::Specification.new do |gem|

gem.add_dependency 'redis'

gem.add_development_dependency 'rspec'
gem.add_development_dependency 'rspec', '~> 3.0'
gem.add_development_dependency 'fakeredis'
gem.add_development_dependency 'timecop'
gem.add_development_dependency 'guard-rspec'
Expand Down
Loading