Sha256: f35f83a77fd0af954fed0f361c131e40e58f08b768ceda992dd5f8db2817fb76

Contents?: true

Size: 1.63 KB

Versions: 27

Compression:

Stored size: 1.63 KB

Contents

require 'digest/sha1'
require_relative 'rate_limiting/redis_script'

module Bearcat
  module RateLimiting
    LEAK_RATE = 10
    GUESS_COST = 60
    MAXIMUM = 600

    class RateLimiter
      attr_reader :namespace

      def initialize(namespace: "bearcat", **kwargs)
        @namespace = namespace
        @params = kwargs
      end

      def apply(key, guess: GUESS_COST, on_sleep: nil, max_sleep: 15)
        current = increment("#{key}", 0, guess)
        cost = guess
        remaining = MAXIMUM - current[:count]

        if remaining < 0
          tts = -remaining / LEAK_RATE
          tts = [tts, max_sleep].min if max_sleep
          on_sleep.call(tts) if on_sleep
          sleep tts
        end

        cost = yield
      ensure
        increment(key, (cost || 0), -guess)
      end
    end

    class RedisLimiter < RateLimiter
      INCR = RedisScript.new(Pathname.new(__FILE__) + "../rate_limiting/increment_bucket.lua")

      def increment(key, amount, pending_amount = 0)
        ts = Time.now.to_f

        redis do |r|
          actual, timestamp = INCR.call(r, ["#{key}|reported"], [amount, ts, LEAK_RATE, MAXIMUM + 300])
          {
            count: actual.to_f,
            timestamp: timestamp.to_f,
          }
        end
      end

      def checkin_known(key, remaining_time)
        redis do |r|
          r.mapped_hmset("#{key}|reported", {
            count: MAXIMUM + 200 - remaining_time,
            timestamp: Time.now.to_f,
          })
        end
      end

      def redis(&blk)
        if @params[:redis]
          @params[:redis].call(blk)
        else
          ::Bearcat.redis(&blk)
        end
      end
    end
  end
end

Version data entries

27 entries across 27 versions & 1 rubygems

Version Path
bearcat-1.5.37 lib/bearcat/rate_limiting.rb
bearcat-1.5.36 lib/bearcat/rate_limiting.rb
bearcat-1.5.35 lib/bearcat/rate_limiting.rb
bearcat-1.5.34 lib/bearcat/rate_limiting.rb
bearcat-1.5.33 lib/bearcat/rate_limiting.rb
bearcat-1.5.32 lib/bearcat/rate_limiting.rb
bearcat-1.5.31 lib/bearcat/rate_limiting.rb
bearcat-1.5.30 lib/bearcat/rate_limiting.rb
bearcat-1.5.29 lib/bearcat/rate_limiting.rb
bearcat-1.5.28 lib/bearcat/rate_limiting.rb
bearcat-1.5.28.beta1 lib/bearcat/rate_limiting.rb
bearcat-1.5.26 lib/bearcat/rate_limiting.rb
bearcat-1.5.24 lib/bearcat/rate_limiting.rb
bearcat-1.5.23 lib/bearcat/rate_limiting.rb
bearcat-1.5.20 lib/bearcat/rate_limiting.rb
bearcat-1.5.19 lib/bearcat/rate_limiting.rb
bearcat-1.5.17 lib/bearcat/rate_limiting.rb
bearcat-1.5.16 lib/bearcat/rate_limiting.rb
bearcat-1.5.15 lib/bearcat/rate_limiting.rb
bearcat-1.5.14 lib/bearcat/rate_limiting.rb