pyrate_limiter.buckets.redis_bucket module¶
Bucket implementation using Redis
- class pyrate_limiter.buckets.redis_bucket.LuaScript¶
Bases:
objectScripts that deal with bucket operations
- PUT_ITEM = '\n local bucket = KEYS[1]\n local now = ARGV[1]\n local space_required = tonumber(ARGV[2])\n local item_name = ARGV[3]\n local rates_count = tonumber(ARGV[4])\n\n -- Per rate the client supplies (window_start, limit, blocking_rank); the\n -- window bounds and rank come from the algorithm, so this script stays\n -- policy-agnostic. blocking_rank < 0 means "resolve no entry".\n for i=1,rates_count do\n local offset = (i - 1) * 3\n local window_start = tonumber(ARGV[5 + offset])\n local limit = tonumber(ARGV[5 + offset + 1])\n local blocking_rank = tonumber(ARGV[5 + offset + 2])\n local count = redis.call(\'ZCOUNT\', bucket, window_start, now)\n local space_available = limit - tonumber(count)\n if space_available < space_required then\n local blocking_timestamp = -1\n\n if blocking_rank >= 0 then\n local blocking = redis.call(\'ZRANGE\', bucket, -1 - blocking_rank, -1 - blocking_rank, \'WITHSCORES\')\n if blocking[2] then\n blocking_timestamp = tonumber(blocking[2])\n end\n end\n\n return {i - 1, blocking_timestamp}\n end\n end\n\n local batch = {}\n -- Each member adds two unpacked arguments; 1000 stays below Lua 5.1 limits.\n local batch_size = 1000\n\n for i=1,space_required do\n batch[#batch + 1] = now\n batch[#batch + 1] = item_name..i\n\n if #batch == batch_size * 2 then\n redis.call(\'ZADD\', bucket, unpack(batch))\n batch = {}\n end\n end\n\n if #batch > 0 then\n redis.call(\'ZADD\', bucket, unpack(batch))\n end\n\n return {-1, -1}\n '¶
- class pyrate_limiter.buckets.redis_bucket.RedisBucket(rates, redis, bucket_key, script_hash, algorithm=None)¶
Bases:
AbstractBucketA bucket using redis for storing data - We are not using redis’ built-in TIME since it is non-deterministic - In distributed context, use local server time or a remote time server - Each bucket instance use a dedicated connection to avoid race-condition - can be either sync or async
- bucket_key¶
- count()¶
Count number of items in the bucket
- flush()¶
Flush the whole bucket - Must remove failing-rate after flushing
- classmethod init(rates, redis, bucket_key, algorithm=None)¶
- leak(current_timestamp=None)¶
leaking bucket - removing items that are outdated
- Return type:
int|Awaitable[int]
- now()¶
Retrieve current timestamp from the clock backend.
- peek(index)¶
Peek at the rate-item at a specific index in latest-to-earliest order NOTE: The reason we cannot peek from the start of the queue(earliest-to-latest) is we can’t really tell how many outdated items are still in the queue
- put(item)¶
Add item to key
- Return type:
bool|Awaitable[bool]
- redis¶
- script_hash¶