Простое ограничение скорости служебный класс, написанный на языке Ruby


У меня следующая простая ставка ограничить коммунальные класса, написанного на Ruby. Его функция достаточно проста и работает за мои намерения. Он использует переменную класса управление/обмен все метки через мое приложение и мьютекс, так что только ограничение скорости осуществляется одновременно.

Код очищает истек метки перед запуском, так что массив меток времени, только имеет срок действия не истек метки сохраняются.

  class RateLimit
    @@timestamp = {}
    @@m = Mutex.new

    def initialize(max, interval, name)
      @max, @interval, @name = max, interval, name
      @@timestamp[name] = [] if @@timestamp[name].nil? # only create a new rate limit
                                                       # entry if it doesn't exist
    end

    def validate_rate?
      @@m.synchronize do

        # removes expired entries from the array
        @@timestamp[@name].delete_if { |ts| self.is_expired?(ts) } unless @@timestamp[@name].empty?

        # Since we automatically clean up expired timestamps, the number of items
        # in the timestamp hash is always going to be the number of non-expired items.
        # If the number of non-expired items is under the max, we let the request go
        # through and also add this timestamp to the array
        # If the number of non-expired items is greater than or equal to the max, then
        # we don't let the request go through
        if @@timestamp[@name].count < @max
          @@timestamp[@name] << Time.now
          return true
        else
          return false
        end
      end
    end

    def is_expired?(timestamp)
      timestamp <= Time.now - @interval
    end

    def message
      "You are doing this too many times. Please try again in #{@interval} seconds."
    end

  end

Чтобы использовать этот класс, вы просто выполните следующие действия:

  rl = RateLimit.new(5, 5.minutes, 'a_name_for_this_request')
  if rl.validate_rate?
    # do stuff
  else
    # wait for 10 seconds.. or throw the exception.. or log this to warn the admin
    Log(rl.message)
  end


96
0
задан 11 апреля 2018 в 09:04 Источник Поделиться
Комментарии