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