Skip to content

Instantly share code, notes, and snippets.

@commitshappen
Last active November 9, 2021 21:09
Show Gist options
  • Save commitshappen/7868fa087cbeae65a61384e177201d0c to your computer and use it in GitHub Desktop.
Save commitshappen/7868fa087cbeae65a61384e177201d0c to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
# @see https://gist.github.com/commitshappen/5928740df2e01f256778c2dbd14364a5 for the RateLimiter
module RateLimitable
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def rate_limiter(bucket_name, global: {}, local: {})
@rate_limits = { bucket_name: bucket_name, global: global, local: local }
end
def rate_limits
@rate_limits ||= rate_limiter(nil)
end
end
def method_missing(method_name, ...)
if method_name.start_with?("rate_limited_")
within_rate_limit { public_send(method_name.to_s.delete_prefix("rate_limited_"), ...) }
else
super(method_name, ...)
end
end
def within_rate_limit(&block)
rate_limiters[:local].within_limit do
rate_limiters[:global].within_limit(&block)
end
end
private
def generate_rate_limiter(namespace)
rate_limit_namespace = namespace == :local ? self.object_id : nil
rate_limit_bucket = [rate_limits[:bucket_name], rate_limit_namespace].compact.join(":")
RateLimiter.new(rate_limit_bucket, rate_limits[namespace])
end
def rate_limits
self.class.rate_limits
end
def rate_limiters
@rate_limiters ||= { global: generate_rate_limiter(:global), local: generate_rate_limiter(:local) }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment