pydle
pydle copied to clipboard
Flood model needs some re-thinking
Currently, pydle's flood model is very limited in its possibilites:
- It follows a burst -> delay -> burst -> delay model, which is not how IRC servers expect to receive messages. Typically, a burst -> delay -> message -> delay -> message is folllowed in actual client implementations.
- It fails to properly take floating point delays into account.
- It is globally configured as part of the (undocumented)
pydle.connection
module, and should be configurable per-client. - The current code in
pydle.connection.Connection._on_write
is messy.
I didn't realize pydle even had a flood control model until I saw this issue -- after implementing my own solution in an IRC bot framework I'm working on.
I wrote a solution here that you're welcome to adopt, though it probably needs some improvements to play nicer with asyncio and hasn't been extensively tested. That said, the basic concept is:
- Have a 'bucket' that holds
burst
units and refills at a rate of 1 unit everyrate
seconds. - Have a
collections.deque
of pending events and how much one event 'costs' (Usually the cost is 1 unit) -
Throttle.tick()
figures out how long it has been since the last tick, refills the bucket accordingly, and then pulls events from the queue (drainingcost
units from the bucket each time) - All functions involving the queue (including
tick
) return atimedelta
of how long the caller should wait before ticking the queue again. This will be None if the queue is empty and the bucket is full. - Events are simply zero-argument callables (or made that way using functools.partial) that are called when they are pulled from the queue.
Updated link with a different, cleaner implementation:
https://github.com/dewiniaid/pydle-ircbot/blob/b85cb5bed4113099bab36be93a283a7daeb0088a/util.py#L34