Class: Pause::Action
- Inherits:
-
Object
- Object
- Pause::Action
- Defined in:
- lib/pause/action.rb
Class Attribute Summary collapse
-
.checks ⇒ Object
Returns the value of attribute checks.
Instance Attribute Summary collapse
-
#identifier ⇒ Object
Returns the value of attribute identifier.
Class Method Summary collapse
- .adapter ⇒ Object
-
.check(*args, **opts) ⇒ Object
Action subclasses should define their checks as follows.
- .disable ⇒ Object
- .disabled? ⇒ Boolean
-
.enable ⇒ Object
Actions can be globally disabled or re-enabled in a persistent way.
- .enabled? ⇒ Boolean
- .inherited(klass) ⇒ Object
- .rate_limited_identifiers ⇒ Object
- .tracked_identifiers ⇒ Object
- .unblock_all ⇒ Object
Instance Method Summary collapse
- #analyze(recalculate: false) ⇒ Object
- #block_for(ttl) ⇒ Object
- #checks ⇒ Object
- #if_rate_limited {|check_result| ... } ⇒ Object
- #increment!(count = 1, timestamp = Time.now.to_i) ⇒ Object
-
#initialize(identifier, &block) ⇒ Action
constructor
A new instance of Action.
- #ok? ⇒ Boolean
- #rate_limited? ⇒ Boolean
- #scope ⇒ Object
- #unblock ⇒ Object
- #unless_rate_limited(count: 1, timestamp: Time.now.to_i, &_block) ⇒ Object
Constructor Details
#initialize(identifier, &block) ⇒ Action
Returns a new instance of Action.
7 8 9 10 11 |
# File 'lib/pause/action.rb', line 7 def initialize(identifier, &block) @identifier = identifier self.class.checks ||= [] instance_exec(&block) if block end |
Class Attribute Details
.checks ⇒ Object
Returns the value of attribute checks.
18 19 20 |
# File 'lib/pause/action.rb', line 18 def checks @checks end |
Instance Attribute Details
#identifier ⇒ Object
Returns the value of attribute identifier.
5 6 7 |
# File 'lib/pause/action.rb', line 5 def identifier @identifier end |
Class Method Details
.check(*args, **opts) ⇒ Object
Action subclasses should define their checks as follows
period_seconds - compare all activity by an identifier within the time period
max_allowed - if the number of actions by an identifier exceeds max_allowed for the time period marked
by period_seconds, it is no longer ok.
block_ttl - time to mark identifier as not ok
class MyAction < Pause::Action
check period_seconds: 60, max_allowed: 100, block_ttl: 3600
check period_seconds: 1800, max_allowed: 2000, block_ttl: 3600
end
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/pause/action.rb', line 78 def check(*args, **opts) self.checks ||= [] params = if args.empty? # if block_ttl is not provided, just default to the period opts[:block_ttl] ||= opts[:period_seconds] [opts[:period_seconds], opts[:max_allowed], opts[:block_ttl]] else args end self.checks << Pause::PeriodCheck.new(*params) end |
.disable ⇒ Object
54 55 56 |
# File 'lib/pause/action.rb', line 54 def disable adapter.disable(scope) end |
.disabled? ⇒ Boolean
62 63 64 |
# File 'lib/pause/action.rb', line 62 def disabled? !enabled? end |
.enable ⇒ Object
Actions can be globally disabled or re-enabled in a persistent way.
MyAction.disable
MyAction.enabled? => false
MyAction.disabled? => true
MyAction.enable
MyAction.enabled? => true
MyAction.disabled? => false
50 51 52 |
# File 'lib/pause/action.rb', line 50 def enable adapter.enable(scope) end |
.enabled? ⇒ Boolean
58 59 60 |
# File 'lib/pause/action.rb', line 58 def enabled? adapter.enabled?(scope) end |
.inherited(klass) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/pause/action.rb', line 20 def inherited(klass) klass.instance_eval do # Action subclasses should define their scope as follows # # class MyAction < Pause::Action # scope "my:scope" # end # @scope = klass.name.downcase.gsub('::', '.') class << self # @param [String] args def scope(*args) @scope = args.first if args && args.size == 1 @scope end end end end |
.rate_limited_identifiers ⇒ Object
97 98 99 |
# File 'lib/pause/action.rb', line 97 def rate_limited_identifiers adapter.rate_limited_keys(scope) end |
.tracked_identifiers ⇒ Object
93 94 95 |
# File 'lib/pause/action.rb', line 93 def tracked_identifiers adapter.all_keys(scope) end |
.unblock_all ⇒ Object
101 102 103 |
# File 'lib/pause/action.rb', line 101 def unblock_all adapter.delete_rate_limited_keys(scope) end |
Instance Method Details
#analyze(recalculate: false) ⇒ Object
148 149 150 |
# File 'lib/pause/action.rb', line 148 def analyze(recalculate: false) Pause.analyzer.check(self, recalculate: recalculate) end |
#block_for(ttl) ⇒ Object
129 130 131 |
# File 'lib/pause/action.rb', line 129 def block_for(ttl) adapter.rate_limit!(scope, identifier, ttl) end |
#checks ⇒ Object
125 126 127 |
# File 'lib/pause/action.rb', line 125 def checks self.class.checks end |
#if_rate_limited {|check_result| ... } ⇒ Object
120 121 122 123 |
# File 'lib/pause/action.rb', line 120 def if_rate_limited(&) check_result = analyze(recalculate: true) yield(check_result) unless check_result.nil? end |
#increment!(count = 1, timestamp = Time.now.to_i) ⇒ Object
133 134 135 |
# File 'lib/pause/action.rb', line 133 def increment!(count = 1, = Time.now.to_i) adapter.increment(scope, identifier, , count) end |
#ok? ⇒ Boolean
141 142 143 144 145 146 |
# File 'lib/pause/action.rb', line 141 def ok? Pause.analyzer.check(self).nil? rescue ::Redis::CannotConnectError => e Pause::Logger.fatal "Error connecting to redis: #{e.inspect} #{e.} #{e.backtrace.join("\n")}" false end |
#rate_limited? ⇒ Boolean
137 138 139 |
# File 'lib/pause/action.rb', line 137 def rate_limited? !ok? end |
#scope ⇒ Object
13 14 15 |
# File 'lib/pause/action.rb', line 13 def scope self.class.scope end |
#unblock ⇒ Object
152 153 154 |
# File 'lib/pause/action.rb', line 152 def unblock adapter.delete_rate_limited_key(scope, identifier) end |
#unless_rate_limited(count: 1, timestamp: Time.now.to_i, &_block) ⇒ Object
110 111 112 113 114 115 116 117 118 |
# File 'lib/pause/action.rb', line 110 def unless_rate_limited(count: 1, timestamp: Time.now.to_i, &_block) check_result = analyze if check_result.nil? yield increment!(count, ) else check_result end end |