Rate Limiter / Cool Down timer in python3 and redis

My main source of data… jira service desk… cannot be trusted. Oh yes, 90% of the time it acts sane, but once in a while, someone misconfigures a big panda alert and we get 1000 new incidents in moments.

My colleague got flooded with pager duties and emails one Saturday, and I’m sure it made him cry. I need to rate limit these actions.

My plan is to use incr function to increment a redis key. The idea is that you create a new key every x seconds, with an expiry (equal to x) and then when you increment redis will respond with the current value, so you can just test the if loop.

First things first. I know how to do something every second int(time)) but every 10 minutes?

from time import time, sleep
while True:
     everyXSeconds = 10
     curTime = int(time())
     key = curTime - curTime % everyXSeconds

I’m only calling time() once because calling time() twice in the mod actually give different nanosecond values… and I just know I am going to hit some corner case where that crosses a second boundary and messes up EVERYTHING

BUT… the above is actually crap and not needed at all. That is a crap way to rate limit cause, for example, if I am trying to stop an email flood it will still send 10 emails every X seconds. As in, the count will be reset every X seconds.

To me the following makes a bit more sense:

while True:
    curTime = time()
    print(f"curTime is {curTime}")
    everyXSeconds = 10
    rateBeginTime = curTime - everyXSeconds
    count = red.zcount(queueName, rateBeginTime, curTime)
    print(f"current hit queue is :{count}")
    limitMap = {curTime: curTime}
    red.zadd(queueName, limitMap)
    remove = red.zremrangebyscore(queueName, 0, rateBeginTime)
    print(f"removed {remove} keys")

So thats just what I used to test…. but basically you are using a sorted list and adding and removing as needed

Leave a Reply

Your email address will not be published. Required fields are marked *