Изменение кэширования сообщений

This commit is contained in:
2025-10-19 19:22:07 +03:00
parent de1c82c267
commit 459ed66e9a
2 changed files with 89 additions and 15 deletions

View File

@@ -92,6 +92,24 @@ class Database: # Инициализация класса
ON users(tag COLLATE NOCASE) ON users(tag COLLATE NOCASE)
''') ''')
# Таблица для кэша сообщений (для обработки реакций)
cursor.execute('''
CREATE TABLE IF NOT EXISTS message_cache (
chat_id INTEGER NOT NULL,
message_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
thread_id INTEGER,
timestamp INTEGER NOT NULL,
PRIMARY KEY (chat_id, message_id)
)
''')
# Индекс для быстрой очистки старых записей
cursor.execute('''
CREATE INDEX IF NOT EXISTS idx_message_cache_timestamp
ON message_cache(timestamp)
''')
connect.commit() connect.commit()
logger.info("База данных и индексы успешно инициализированы") logger.info("База данных и индексы успешно инициализированы")
@@ -395,5 +413,52 @@ class Database: # Инициализация класса
connect.commit() connect.commit()
logger.info(f"Пользователь {from_user_id} поблагодарил {to_user_id} в чате {chat_id}") logger.info(f"Пользователь {from_user_id} поблагодарил {to_user_id} в чате {chat_id}")
# Добавляет сообщение в кэш
def cache_message(self, chat_id: int, message_id: int, user_id: int, thread_id: Optional[int] = None):
with self._get_connection() as connect:
cursor = connect.cursor()
current_time = int(time.time())
cursor.execute('''
INSERT OR REPLACE INTO message_cache (chat_id, message_id, user_id, thread_id, timestamp)
VALUES (?, ?, ?, ?, ?)
''', (chat_id, message_id, user_id, thread_id, current_time))
connect.commit()
# Получает информацию о сообщении из кэша
# Возвращает (user_id, thread_id) или None если не найдено
def get_cached_message(self, chat_id: int, message_id: int) -> Optional[Tuple[int, Optional[int]]]:
with self._get_connection() as connect:
cursor = connect.cursor()
cursor.execute('''
SELECT user_id, thread_id
FROM message_cache
WHERE chat_id = ? AND message_id = ?
''', (chat_id, message_id))
result = cursor.fetchone()
return result if result else None
# Очищает сообщения старше указанного времени (по умолчанию 24 часа)
def cleanup_old_messages(self, max_age_seconds: int = 86400):
with self._get_connection() as connect:
cursor = connect.cursor()
cutoff_time = int(time.time()) - max_age_seconds
cursor.execute('''
DELETE FROM message_cache
WHERE timestamp < ?
''', (cutoff_time,))
deleted_count = cursor.rowcount
connect.commit()
if deleted_count > 0:
logger.info(f"Удалено {deleted_count} старых сообщений из кэша")
return deleted_count
# Получает количество сообщений в кэше
def get_cache_size(self) -> int:
with self._get_connection() as connect:
cursor = connect.cursor()
cursor.execute('SELECT COUNT(*) FROM message_cache')
result = cursor.fetchone()
return result[0] if result else 0
# Создаем экземпляр базы данных для импорта в других модулях # Создаем экземпляр базы данных для импорта в других модулях
db = Database() db = Database()

View File

@@ -2,7 +2,6 @@ from telebot.async_telebot import AsyncTeleBot
from telebot.types import Message, MessageReactionUpdated, ReactionTypeEmoji from telebot.types import Message, MessageReactionUpdated, ReactionTypeEmoji
import asyncio import asyncio
import logging import logging
from collections import OrderedDict
from database import db from database import db
from thank_words import contains_thank_word from thank_words import contains_thank_word
@@ -11,29 +10,39 @@ from config import THANK_COOLDOWN
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Кэш для хранения message_id -> (user_id, message_thread_id) (последние 1000 сообщений) # Фоновая задача для автоочистки старых сообщений
# Используем OrderedDict для автоматического удаления старых записей _cleanup_task = None
_message_cache = OrderedDict()
_MAX_CACHE_SIZE = 1000
def _cache_message(chat_id: int, message_id: int, user_id: int, message_thread_id: int = None): def _cache_message(chat_id: int, message_id: int, user_id: int, message_thread_id: int = None):
"""Добавляет сообщение в кэш""" """Добавляет сообщение в кэш БД"""
key = f"{chat_id}:{message_id}" db.cache_message(chat_id, message_id, user_id, message_thread_id)
_message_cache[key] = (user_id, message_thread_id)
# Удаляем старые записи, если кэш переполнен
if len(_message_cache) > _MAX_CACHE_SIZE:
_message_cache.popitem(last=False)
def _get_cached_message(chat_id: int, message_id: int): def _get_cached_message(chat_id: int, message_id: int):
"""Получает (user_id, message_thread_id) из кэша""" """Получает (user_id, message_thread_id) из кэша БД"""
key = f"{chat_id}:{message_id}" return db.get_cached_message(chat_id, message_id)
return _message_cache.get(key)
async def _cleanup_old_cache():
"""Фоновая задача для очистки старых сообщений из кэша каждый час"""
while True:
try:
await asyncio.sleep(3600) # Ждём 1 час
deleted = db.cleanup_old_messages(max_age_seconds=86400) # Удаляем старше 24 часов
cache_size = db.get_cache_size()
logger.info(f"[CACHE CLEANUP] Размер кэша: {cache_size} сообщений")
except Exception as e:
logger.error(f"[CACHE CLEANUP] Ошибка очистки кэша: {e}", exc_info=True)
def register_handlers(bot: AsyncTeleBot): def register_handlers(bot: AsyncTeleBot):
"""Регистрирует обработчики для отслеживания благодарностей""" """Регистрирует обработчики для отслеживания благодарностей"""
logger.info("Регистрация обработчика благодарностей (karma_tracker)") logger.info("Регистрация обработчика благодарностей (karma_tracker)")
# Запускаем фоновую задачу очистки старых сообщений из кэша
global _cleanup_task
if _cleanup_task is None or _cleanup_task.done():
_cleanup_task = asyncio.create_task(_cleanup_old_cache())
cache_size = db.get_cache_size()
logger.info(f"[CACHE] Запущена автоочистка кэша. Текущий размер: {cache_size} сообщений")
@bot.message_reaction_handler(func=lambda m: True) @bot.message_reaction_handler(func=lambda m: True)
async def handle_reaction(reaction: MessageReactionUpdated): async def handle_reaction(reaction: MessageReactionUpdated):
""" """