I'm trying to replace the sql implementation of Drupal 8's flood control service with a redis based implementation.
See https://github.com/drupal/drupal/blob/8.0.x/core/lib/Drupal/Core/Flood/DatabaseBackend.php
The requirements are like this:
My thoughts on how to implement this:
After writing all this down, I might actually have an idea how it could work, so I guess what I'm looking for is feedback on whether that makes sense or if there's an easier way.
Each event:identifier combination is a key and contains a sorted set. That uses the expiration as score and as value a unique value, possibly creation time in microseconds. I count the non-expired records to detect if the threshold was reached. I'm updating the expiration of each event:identifier to the provided expiration window, so it will be auto-deleted assuming unless a given identifier/client doesn't give up and keeps on trying, without ever reaching the expiration. Is it worth to clean up the records inside a set e.g. when doing a new register? It seems to be fairly fast, and I could also only do it sometimes.
I would prefer to use Redis' key expiration feature, instead of reimplementing one.
A simpler alternative would be the following one:
SETNX <identifier>:<event type> 1
if the response is 1, this is the first attempt, so you set a timeout on this key:
EXPIRE <identifier>:<event type> <timeout in seconds>
otherwise you increment the number of attempts
INCR <identifier>:<event type>
The response of the INCR will give you the number of attempts during the window, so you know if you can allow the action or not.
You could also use a hash instead of a simple value, if you need to store more data, like the max number of allowed attempts in the given time window. In this case you will probably use HSETNX and HINCR.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With