Skip to content

Wait to execute helper #4

@ishields

Description

@ishields

So I'm not sure if this belongs in this gem but I feel like it's a fairly common use case. If it doesn't belong directly in the gem perhaps an example in the readme could help someone?

So I needed to rate limit a particular method but rather than just skipping the execution if the limit was hit, I needed to always guarantee the method was eventually executed. So I combine ExcessFlow with a simple while (true) and a sleep such that eventually the method completes once it can without violating the limit.

Here is my code. Also if I missed something already built into the gem that does this easier please let me know!

module RateLimit
  module_function

  def limit(unique_throttle_name, rate, interval, &block)
    while true
      execution = ExcessFlow.throttle(options(unique_throttle_name, rate, interval)) do
        block.call
      end

      if execution.success?
        return execution.result
      else
        time_to_wait = interval + 1
        time_to_wait = rand(0.0..time_to_wait.to_f)
        puts "Rate limited - waiting a random amount of time #{time_to_wait}"
        sleep time_to_wait
      end
    end
  end

  def options(name, rate, interval)
    { key: name.to_s, limit: rate, ttl: interval }
  end
end

Usage:

RateLimit.limit("rate-limit-some-unique-name', 1, 10) do
   puts "Performing this block once, no more than every 10 seconds"
end

I run this code inside some sidekiq workers that run asynchronously so I can safely guarantee across processes that the block doesn't execute more than it should, but it still eventually executes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions