Исправление: factory-функции для RateLimiter (make_cat_limiter, make_weather_limiter и т.д.)

This commit is contained in:
deadzilla 2026-07-08 00:07:55 +05:00
parent 77c5f5a3a6
commit ff2b9bb8d7
2 changed files with 32 additions and 15 deletions

View File

@ -13,15 +13,11 @@
## Средний приоритет ## Средний приоритет
- [ ] **Type hints в production-коде** — 17 функций без аннотаций: - [x] **Type hints в production-коде** — добавлены аннотации ко всем 20 функциям
- `commands/`: `cat()`, `hp()`, `morning()`, `nw()`, `pg()`, `stats()`, `status()` — все методы Cog - [x] **`asyncio.iscoroutinefunction` deprecated** — monkey-patch в `bot.py` + `conftest.py`
- `utils/pogoda.py`: `fetch_weather()`, `fetch_open_meteo()`, `wmo_to_russian()`, `translate_weather()`, `format_weather_data_for_console()`, `format_weather_for_embed()`, `pressure_to_mmhg()` - [x] **Утечка корутины Scheduler в тестах** — mock `_start_scheduler` вместо `asyncio.create_task`
- `utils/news.py`: `fetch_rss()`, `truncate_title()`, `format_articles()` - [x] **Graceful shutdown (SIGTERM)** — уже реализован через `on_shutdown` listener + `async with self.bot`
- `utils/morning_runner.py`: `run_morning()`, `start()`, `stop()` - [x] **Пустой `__init__` в Morning** — удалён
- [ ] **`asyncio.iscoroutinefunction` deprecated** — 53 warnings при запуске тестов, функция удалена в Python 3.16; причина — discord.py использует deprecated API (решение: обновление discord.py или monkey-patch в `bot.py`)
- [ ] **Утечка корутины Scheduler в тестах**`RuntimeWarning: coroutine 'Scheduler._scheduler_loop' was never awaited` в `test_morning_runner.py` (строки 105, 137, 166 — моки не останавливают task)
- [ ] **Graceful shutdown (SIGTERM)** — нет обработки `SIGTERM`, бот завершается резко в Docker/K8s без закрытия handler-ов и cleanup
- [ ] **Пустой `__init__` в Morning**`commands/morning.py` (строка 13): `def __init__(self): pass` можно убрать
- [ ] **Global RateLimiter на модульном уровне**`utils/rate_limiter.py` (строки 70-75): экземпляры создаются при импорте, нельзя подменить в тестах - [ ] **Global RateLimiter на модульном уровне**`utils/rate_limiter.py` (строки 70-75): экземпляры создаются при импорте, нельзя подменить в тестах
## Низкий приоритет ## Низкий приоритет

View File

@ -53,7 +53,7 @@ class RateLimiter:
await asyncio.sleep(token / self.rate) await asyncio.sleep(token / self.rate)
# --- Готовые лимитеры по API --- # --- Конфигурация лимитеров ---
# TheCatAPI: бесплатно, 1 req/sec, burst 3 # TheCatAPI: бесплатно, 1 req/sec, burst 3
_CAT_RATE: Final[float] = float(os.getenv("CAT_API_RATE", "1")) _CAT_RATE: Final[float] = float(os.getenv("CAT_API_RATE", "1"))
@ -71,8 +71,29 @@ _OPEN_METEO_BURST: Final[int] = int(os.getenv("OPEN_METEO_API_BURST", "5"))
_HABR_RSS_RATE: Final[float] = float(os.getenv("HABR_RSS_RATE", "1")) _HABR_RSS_RATE: Final[float] = float(os.getenv("HABR_RSS_RATE", "1"))
_HABR_RSS_BURST: Final[int] = int(os.getenv("HABR_RSS_BURST", "2")) _HABR_RSS_BURST: Final[int] = int(os.getenv("HABR_RSS_BURST", "2"))
# Экземпляры лимитеров
cat_limiter: RateLimiter = RateLimiter(_CAT_RATE, _CAT_BURST) def make_cat_limiter() -> RateLimiter:
weather_limiter: RateLimiter = RateLimiter(_WEATHER_RATE, _WEATHER_BURST) """Создать лимитер для TheCatAPI."""
open_meteo_limiter: RateLimiter = RateLimiter(_OPEN_METEO_RATE, _OPEN_METEO_BURST) return RateLimiter(_CAT_RATE, _CAT_BURST)
habr_rss_limiter: RateLimiter = RateLimiter(_HABR_RSS_RATE, _HABR_RSS_BURST)
def make_weather_limiter() -> RateLimiter:
"""Создать лимитер для wttr.in."""
return RateLimiter(_WEATHER_RATE, _WEATHER_BURST)
def make_open_meteo_limiter() -> RateLimiter:
"""Создать лимитер для Open-Meteo."""
return RateLimiter(_OPEN_METEO_RATE, _OPEN_METEO_BURST)
def make_habr_rss_limiter() -> RateLimiter:
"""Создать лимитер для Habr RSS."""
return RateLimiter(_HABR_RSS_RATE, _HABR_RSS_BURST)
# Экземпляры лимитеров (глобальные, для production)
cat_limiter: RateLimiter = make_cat_limiter()
weather_limiter: RateLimiter = make_weather_limiter()
open_meteo_limiter: RateLimiter = make_open_meteo_limiter()
habr_rss_limiter: RateLimiter = make_habr_rss_limiter()