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

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)
''')
# Таблица для кэша сообщений (для обработки реакций)
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()
logger.info("База данных и индексы успешно инициализированы")
@@ -395,5 +413,52 @@ class Database: # Инициализация класса
connect.commit()
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()

View File

@@ -2,7 +2,6 @@ from telebot.async_telebot import AsyncTeleBot
from telebot.types import Message, MessageReactionUpdated, ReactionTypeEmoji
import asyncio
import logging
from collections import OrderedDict
from database import db
from thank_words import contains_thank_word
@@ -11,29 +10,39 @@ from config import THANK_COOLDOWN
logger = logging.getLogger(__name__)
# Кэш для хранения message_id -> (user_id, message_thread_id) (последние 1000 сообщений)
# Используем OrderedDict для автоматического удаления старых записей
_message_cache = OrderedDict()
_MAX_CACHE_SIZE = 1000
# Фоновая задача для автоочистки старых сообщений
_cleanup_task = None
def _cache_message(chat_id: int, message_id: int, user_id: int, message_thread_id: int = None):
"""Добавляет сообщение в кэш"""
key = f"{chat_id}:{message_id}"
_message_cache[key] = (user_id, message_thread_id)
# Удаляем старые записи, если кэш переполнен
if len(_message_cache) > _MAX_CACHE_SIZE:
_message_cache.popitem(last=False)
"""Добавляет сообщение в кэш БД"""
db.cache_message(chat_id, message_id, user_id, message_thread_id)
def _get_cached_message(chat_id: int, message_id: int):
"""Получает (user_id, message_thread_id) из кэша"""
key = f"{chat_id}:{message_id}"
return _message_cache.get(key)
"""Получает (user_id, message_thread_id) из кэша БД"""
return db.get_cached_message(chat_id, message_id)
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):
"""Регистрирует обработчики для отслеживания благодарностей"""
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)
async def handle_reaction(reaction: MessageReactionUpdated):
"""