Sha256: b607994b5dba5702d14783f4c40dc08dc458817639c746a3240c4154097e20d3

Contents?: true

Size: 1.01 KB

Versions: 7

Compression:

Stored size: 1.01 KB

Contents

# frozen_string_literal: true

# inspired by https://github.com/negativecode/vines/blob/master/lib/vines/token_bucket.rb
class Async::Throttler
  def initialize(capacity, rate, parent: Async::Task.current)
    raise ArgumentError, "capacity must be > 0" unless capacity.positive?
    raise ArgumentError, "rate must be > 0" unless rate.positive?

    @capacity = capacity
    @tokens = capacity
    @rate = rate
    @parent = parent

    @timestamp = Time.new
  end

  def wait(timeout: 0)
    with_timeout(timeout) do
      while @tokens < 1
        fill!
        sleep(1.0 / @rate)
      end
    end

    @tokens -= 1
  end

  def async(parent: @parent, timeout: 0, &)
    wait(timeout:)
    parent.async(&)
  end

  private

  def with_timeout(timeout, &)
    return yield if timeout.zero?

    Fiber.scheduler.with_timeout(timeout, &)
  end

  def fill!
    return if @tokens >= @capacity

    now = Time.new
    @tokens += @rate * (now - @timestamp)
    @tokens = @capacity if @tokens > @capacity
    @timestamp = now
  end
end

Version data entries

7 entries across 7 versions & 1 rubygems

Version Path
async-tools-0.2.10 lib/async/throttler.rb
async-tools-0.2.9 lib/async/throttler.rb
async-tools-0.2.8 lib/async/throttler.rb
async-tools-0.2.7 lib/async/throttler.rb
async-tools-0.2.6 lib/async/throttler.rb
async-tools-0.2.5 lib/async/throttler.rb
async-tools-0.2.4 lib/async/throttler.rb