клоунада 2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
dv 2026-03-16 00:14:09 +03:00
parent 2338e5666a
commit c48998e085
2 changed files with 54 additions and 33 deletions

View file

@ -13,12 +13,29 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
import time
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def _timed(label: str):
"""Context manager: логирует старт и завершение операции с временем выполнения."""
import contextlib
@contextlib.contextmanager
def _cm():
log.info("%s ...", label)
t0 = time.monotonic()
try:
yield
finally:
log.info("%s%.2fs", label, time.monotonic() - t0)
return _cm()
# ── Агностичное представление клавиатуры ────────────────────────────────────── # ── Агностичное представление клавиатуры ──────────────────────────────────────
@dataclass @dataclass
@ -104,48 +121,46 @@ class TelegramChannelNotifier(Notifier):
# ── Реализация интерфейса ────────────────────────────────────────────────── # ── Реализация интерфейса ──────────────────────────────────────────────────
def send(self, text: str, keyboard: Keyboard | None = None) -> int: def send(self, text: str, keyboard: Keyboard | None = None) -> int:
log.info("Telegram send_message → channel %s", self._channel_id) with _timed(f"send_message → channel {self._channel_id}"):
msg = self._bot.send_message( msg = self._bot.send_message(
self._channel_id, text, self._channel_id, text,
parse_mode="Markdown", parse_mode="Markdown",
disable_web_page_preview=True, disable_web_page_preview=True,
reply_markup=self._to_markup(keyboard), reply_markup=self._to_markup(keyboard),
) )
log.info("Telegram send_message OK, message_id=%s", msg.message_id) log.info("send_message OK → message_id=%s", msg.message_id)
return msg.message_id return msg.message_id
def edit_text(self, message_id: int, text: str, keyboard: Keyboard | None = None): def edit_text(self, message_id: int, text: str, keyboard: Keyboard | None = None):
log.info("Telegram edit_message_text → message_id=%s", message_id) with _timed(f"edit_message_text → message_id={message_id}"):
self._bot.edit_message_text( self._bot.edit_message_text(
text, self._channel_id, message_id, text, self._channel_id, message_id,
parse_mode="Markdown", parse_mode="Markdown",
disable_web_page_preview=True, disable_web_page_preview=True,
reply_markup=self._to_markup(keyboard), reply_markup=self._to_markup(keyboard),
) )
log.info("Telegram edit_message_text OK, message_id=%s", message_id)
def edit_keyboard(self, message_id: int, keyboard: Keyboard | None): def edit_keyboard(self, message_id: int, keyboard: Keyboard | None):
log.info("Telegram edit_message_reply_markup → message_id=%s", message_id) with _timed(f"edit_message_reply_markup → message_id={message_id}"):
self._bot.edit_message_reply_markup( self._bot.edit_message_reply_markup(
self._channel_id, message_id, self._channel_id, message_id,
reply_markup=self._to_markup(keyboard), reply_markup=self._to_markup(keyboard),
) )
def delete(self, message_id: int): def delete(self, message_id: int):
log.info("Telegram delete_message → message_id=%s", message_id) with _timed(f"delete_message → message_id={message_id}"):
try: try:
self._bot.delete_message(self._channel_id, message_id) self._bot.delete_message(self._channel_id, message_id)
log.info("Telegram delete_message OK, message_id=%s", message_id) except Exception as e:
except Exception as e: log.warning("delete_message failed (message_id=%s): %s", message_id, e)
log.warning("Telegram delete_message failed (message_id=%s): %s", message_id, e)
def send_animation(self, url: str, disable_notification: bool = True) -> int: def send_animation(self, url: str, disable_notification: bool = True) -> int:
log.info("Telegram send_animation → channel %s", self._channel_id) with _timed(f"send_animation → channel {self._channel_id}"):
msg = self._bot.send_animation( msg = self._bot.send_animation(
self._channel_id, url, self._channel_id, url,
disable_notification=disable_notification, disable_notification=disable_notification,
) )
log.info("Telegram send_animation OK, message_id=%s", msg.message_id) log.info("send_animation OK → message_id=%s", msg.message_id)
return msg.message_id return msg.message_id
def is_stale_error(self, exc: Exception) -> bool: def is_stale_error(self, exc: Exception) -> bool:

View file

@ -10,6 +10,7 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
import time
import config import config
import database import database
@ -50,6 +51,8 @@ def recreate_post(
Изменения ( ...) дедуплицируются по тексту. Изменения ( ...) дедуплицируются по тексту.
Комментарии (💬 ...) и описания (📝 ...) добавляются всегда. Комментарии (💬 ...) и описания (📝 ...) добавляются всегда.
""" """
t0 = time.monotonic()
log.info("recreate_post START task=%s", task_id)
notifier = get_notifier() notifier = get_notifier()
stored = database.get_stored_events(task_id) stored = database.get_stored_events(task_id)
@ -78,6 +81,7 @@ def recreate_post(
}) })
old = database.get_message_data(task_id) old = database.get_message_data(task_id)
log.info("recreate_post task=%s old_msg=%s", task_id, old["message_id"] if old else None)
try: try:
message_id = notifier.send(full_text, keyboard) message_id = notifier.send(full_text, keyboard)
@ -91,6 +95,8 @@ def recreate_post(
if old: if old:
notifier.delete(old["message_id"]) notifier.delete(old["message_id"])
log.info("recreate_post DONE task=%s%.2fs total", task_id, time.monotonic() - t0)
def refresh_responsible(task_id: int, task_number: str): def refresh_responsible(task_id: int, task_number: str):
"""Редактирует текст поста — обновляет блок «В работе».""" """Редактирует текст поста — обновляет блок «В работе»."""