Sha256: 6e0e0b35f35bb0ca2361a53e723d6d5744aac33afefab20f5e5ad4338e076a46

Contents?: true

Size: 1.33 KB

Versions: 2

Compression:

Stored size: 1.33 KB

Contents

# frozen_string_literal: true

require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/time/calculations'
require 'better_rate_limit/redis_connection'

module BetterRateLimit
  module Throttle
    include RedisConnection

    class << self
      def throttle(key, limit:, time_window:)
        now = Time.now.utc
        timestamps_count = redis_client.llen key

        if timestamps_count < limit
          redis_client.multi do
            redis_client.rpush key, now
            redis_client.expire key, time_window.to_i
          end
          true
        else
          first = redis_client.lpop(key)
          redis_client.multi do
            redis_client.rpush key, now
            redis_client.expire key, time_window.to_i
          end

          passing = first.to_time(:utc) < time_window.ago

          unless passing
            notify(key) unless redis_client.exists('failing-rate-limits:' + key)
            redis_client.setex('failing-rate-limits:' + key, time_window.to_i, '1')
          end

          passing
        end
      end

      def clear(key)
        redis_client.del(key)
        redis_client.del("failing-rate-limits:#{key}")
      end

      alias allow? throttle

      def notify(key)
        ActiveSupport::Notifications.instrument 'rate_limit.notify', { rate_limit_key: key }
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
better_rate_limit-0.1.4 lib/better_rate_limit/throttle.rb
better_rate_limit-0.1.3 lib/better_rate_limit/throttle.rb