Class: GRApiManager::RateLimiter

Inherits:
Object
  • Object
show all
Defined in:
lib/gr_api_manager.rb

Overview


RateLimiter — thread-safe sliding-window rate limiter per IP/key.

Supports pluggable storage backends (default: MemoryStore with Mutex). Prevents client flooding and supports distributed stores like Redis.

Defined Under Namespace

Classes: MemoryStore

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_requests:, window_seconds:, store: nil) ⇒ RateLimiter

Returns a new instance of RateLimiter.



241
242
243
244
245
# File 'lib/gr_api_manager.rb', line 241

def initialize(max_requests:, window_seconds:, store: nil)
  @max_requests   = max_requests
  @window_seconds = window_seconds
  @store          = store || MemoryStore.new
end

Instance Attribute Details

#max_requestsObject (readonly)

Returns the value of attribute max_requests.



190
191
192
# File 'lib/gr_api_manager.rb', line 190

def max_requests
  @max_requests
end

#storeObject (readonly)

Returns the value of attribute store.



190
191
192
# File 'lib/gr_api_manager.rb', line 190

def store
  @store
end

#window_secondsObject (readonly)

Returns the value of attribute window_seconds.



190
191
192
# File 'lib/gr_api_manager.rb', line 190

def window_seconds
  @window_seconds
end

Instance Method Details

#allow?(key) ⇒ Boolean

Returns true if the request from key is within the allowed rate.

Returns:

  • (Boolean)


248
249
250
251
252
253
254
255
256
257
258
# File 'lib/gr_api_manager.rb', line 248

def allow?(key)
  if @store.respond_to?(:allow?)
    if @store.method(:allow?).arity == 1
      @store.allow?(key)
    else
      @store.allow?(key, @max_requests, @window_seconds)
    end
  else
    true
  end
end

#cleanup!Object

Removes stale entries — call periodically to prevent memory growth.



274
275
276
277
278
279
280
281
282
# File 'lib/gr_api_manager.rb', line 274

def cleanup!
  if @store.respond_to?(:cleanup!)
    if @store.method(:cleanup!).arity == 0
      @store.cleanup!
    else
      @store.cleanup!(@window_seconds)
    end
  end
end

#remaining(key) ⇒ Object

Remaining requests allowed for key in the current window.



261
262
263
264
265
266
267
268
269
270
271
# File 'lib/gr_api_manager.rb', line 261

def remaining(key)
  if @store.respond_to?(:remaining)
    if @store.method(:remaining).arity == 1
      @store.remaining(key)
    else
      @store.remaining(key, @max_requests, @window_seconds)
    end
  else
    @max_requests
  end
end

#reset!(key = nil) ⇒ Object

Resets counters for a specific key or all keys.



285
286
287
# File 'lib/gr_api_manager.rb', line 285

def reset!(key = nil)
  @store.reset!(key) if @store.respond_to?(:reset!)
end

#statsObject

Summary hash — safe to log or expose on a diagnostic endpoint.



290
291
292
293
# File 'lib/gr_api_manager.rb', line 290

def stats
  tracked = @store.respond_to?(:size) ? @store.size : :external
  { tracked_ips: tracked, max_requests: @max_requests, window_seconds: @window_seconds }
end