|
6 | 6 | import random
|
7 | 7 | import time
|
8 | 8 | import typing
|
| 9 | +import weakref |
9 | 10 | from collections.abc import Awaitable, Hashable, Iterable
|
10 | 11 | from contextlib import suppress
|
11 | 12 | from dataclasses import dataclass
|
@@ -106,6 +107,7 @@ def __init__(self, *, cooldown_duration: float):
|
106 | 107 | self._periodical_cleanup(random.uniform(0, 10)),
|
107 | 108 | name="CooldownManager cleanup",
|
108 | 109 | )
|
| 110 | + weakref.finalize(self, self.cleanup_task.cancel) |
109 | 111 |
|
110 | 112 | def set_cooldown(self, channel: Hashable, call_arguments: Iterable[object]) -> None:
|
111 | 113 | """Set `call_arguments` arguments on cooldown in `channel`."""
|
@@ -145,11 +147,15 @@ async def _periodical_cleanup(self, initial_delay: float) -> None:
|
145 | 147 | Delete stale items every hour after waiting for `initial_delay`.
|
146 | 148 |
|
147 | 149 | The `initial_delay` ensures cleanups are not running for every command at the same time.
|
| 150 | + A strong reference to self is only kept while cleanup is running. |
148 | 151 | """
|
| 152 | + weak_self = weakref.ref(self) |
| 153 | + del self |
| 154 | + |
149 | 155 | await asyncio.sleep(initial_delay)
|
150 | 156 | while True:
|
151 | 157 | await asyncio.sleep(60 * 60)
|
152 |
| - self._delete_stale_items() |
| 158 | + weak_self()._delete_stale_items() |
153 | 159 |
|
154 | 160 | def _delete_stale_items(self) -> None:
|
155 | 161 | """Remove expired items from internal collections."""
|
|
0 commit comments