class Lucid::Shopify::RedisThrottledStrategy
Use Redis to maintain API call limit throttling across threads/processes.
No delay for requests up to half of the call limit.
Constants
- LEAK_RATE
Public Class Methods
new(redis_client: Redis.current)
click to toggle source
@param redis_client [Redis]
# File lib/lucid/shopify/redis_throttled_strategy.rb, line 15 def initialize(redis_client: Redis.current) @redis_client = redis_client end
Public Instance Methods
call(request, &send_request)
click to toggle source
@param request [Request]
@yieldreturn [Response]
@return [Response]
# File lib/lucid/shopify/redis_throttled_strategy.rb, line 24 def call(request, &send_request) interval_key = build_interval_key(request) interval(interval_key) send_request.().tap do |res| header = res.headers['X-Shopify-Shop-Api-Call-Limit'] next if header.nil? cur, max = header.split('/') @redis_client.mapped_hmset(interval_key, cur: cur, max: max, at: timestamp ) end end
Private Instance Methods
interval(interval_key)
click to toggle source
If over half the call limit, sleep until requests leak back to the threshold.
@param interval_key [String]
# File lib/lucid/shopify/redis_throttled_strategy.rb, line 48 def interval(interval_key) cur, max, at = @redis_client.hmget(interval_key, :cur, :max, :at).map(&:to_i) cur = leak(cur, at) delay_threshold = max / 2 # no delay if cur > delay_threshold sleep(Rational((cur - delay_threshold) * LEAK_RATE, 1000)) end end
leak(cur, at)
click to toggle source
Find the actual value of {cur}, by subtracting requests leaked by the leaky bucket algorithm since the value was set.
@param cur [Integer] @param at [Integer]
@return [Integer]
# File lib/lucid/shopify/redis_throttled_strategy.rb, line 67 def leak(cur, at) n = Rational(timestamp - at, LEAK_RATE).floor n > cur ? 0 : cur - n end