Sha256: 66cf78385cb33ccedd727bacce373be0fa7e295a314ee4ba2dab882d051c5f20

Contents?: true

Size: 1.8 KB

Versions: 10

Compression:

Stored size: 1.8 KB

Contents

require 'active_support/core_ext/numeric/time'

module Weeter
  class Limitator
    Result = Struct.new(:status, :limited_keys)

    DO_NOT_LIMIT      = :do_not_limit
    INITIATE_LIMITING = :initiate_limiting
    CONTINUE_LIMITING = :continue_limiting

    module UNLIMITED
      def self.limit_status(*args)
        DO_NOT_LIMIT
      end
    end

    class TimeWindow
      def initialize(options = {})
        @start = options.fetch(:start)
        @duration = options.fetch(:duration)
      end

      def over?(time)
        time - @start > @duration
      end

      def begin_new_window(at)
        @start = at
      end
    end

    attr_accessor :lookup, :window, :max

    def initialize(options = {})
      self.window = TimeWindow.new({
        start: self.now,
        duration: options.fetch(:duration)
      })

      self.max = options.fetch(:max)

      flush
    end

    def process(*keys)
      ensure_correct_window

      keys.each do |key|
        increment(key)
      end

      result = Result.new
      limited_keys = keys.select { |key| exceeds_max?(key) }
      if limited_keys.any?
        result[:limited_keys] = limited_keys
        if limited_keys.any? { |key| exceeds_max_by_one?(key) }
          result[:status] = INITIATE_LIMITING
        else
          result[:status] = CONTINUE_LIMITING
        end
      else
        result[:status] = DO_NOT_LIMIT
      end
      result
    end

  protected

    def now
      Time.now
    end

    def increment(key)
      lookup[key] += 1
    end

    def exceeds_max?(key)
      lookup[key] > max
    end

    def exceeds_max_by_one?(key)
      lookup[key] == max + 1
    end

    def ensure_correct_window
      return unless window.over?(now)

      flush

      window.begin_new_window(now)
    end

    def flush
      self.lookup = Hash.new(0)
    end
  end
end

Version data entries

10 entries across 10 versions & 1 rubygems

Version Path
weeter-0.19.4 lib/weeter/limitator.rb
weeter-0.19.3 lib/weeter/limitator.rb
weeter-0.19.2 lib/weeter/limitator.rb
weeter-0.19.1 lib/weeter/limitator.rb
weeter-0.19.0 lib/weeter/limitator.rb
weeter-0.18.0 lib/weeter/limitator.rb
weeter-0.17.0 lib/weeter/limitator.rb
weeter-0.15.0 lib/weeter/limitator.rb
weeter-0.14.0 lib/weeter/limitator.rb
weeter-0.13.0 lib/weeter/limitator.rb