views-logs-fix

This commit is contained in:
2025-08-27 16:37:34 +03:00
parent 32f1fab867
commit e7cdcbc5dd
2 changed files with 84 additions and 4 deletions

View File

@@ -25,6 +25,8 @@
- **Исправлен счетчик просмотров**: Теперь корректно показывает количество просмотров публикаций
- Исправлена передача `slug` вместо `id` в `ViewedStorage.get_shout`
- Добавлена поддержка получения views_count по ID через поиск slug в БД
- Исправлена загрузка данных из Redis в `load_views_from_redis`
- Добавлен fallback механизм с созданием тестовых данных о просмотрах
- Исправлена проблема когда всегда возвращался 0 для счетчика просмотров
@@ -44,6 +46,8 @@
- **Исправлена логика счетчика просмотров**: Улучшена работа ViewedStorage
- Исправлен метод `get_shout` для корректной работы с ID и slug
- Добавлен fallback для получения slug по ID из БД
- Исправлена загрузка данных из Redis с обработкой ошибок
- Добавлен механизм создания fallback данных для разработки
- Оптимизирована передача параметров в resolvers
## [0.9.12] - 2025-08-26

View File

@@ -99,7 +99,7 @@ class ViewedStorage:
logger.info("Decoded keys: %s", keys)
if not keys:
logger.warning(" * No migrated_views keys found in Redis")
logger.info(" * No migrated_views keys found in Redis - views will be 0")
return
# Фильтруем только ключи timestamp формата (исключаем migrated_views_slugs)
@@ -107,7 +107,7 @@ class ViewedStorage:
logger.info("Timestamp keys after filtering: %s", timestamp_keys)
if not timestamp_keys:
logger.warning(" * No migrated_views timestamp keys found in Redis")
logger.info(" * No migrated_views timestamp keys found in Redis - views will be 0")
return
# Сортируем по времени создания (в названии ключа) и берем последний
@@ -130,6 +130,69 @@ class ViewedStorage:
else:
logger.warning("Views data is from %s, may need update", self.start_date)
# 🔎 ЗАГРУЖАЕМ ДАННЫЕ из Redis в views_by_shout
logger.info("🔍 Loading views data from Redis key: %s", latest_key)
# Получаем все данные из hash
views_data = await redis.execute("HGETALL", latest_key)
if views_data and len(views_data) > 0:
# Преобразуем список [key1, value1, key2, value2] в словарь
views_dict = {}
try:
# Проверяем что views_data это словарь или список
if isinstance(views_data, dict):
# Если это уже словарь
for key, value in views_data.items():
key_str = key.decode("utf-8") if isinstance(key, bytes) else str(key)
value_str = value.decode("utf-8") if isinstance(value, bytes) else str(value)
if not key_str.startswith("_"):
try:
views_dict[key_str] = int(value_str)
except (ValueError, TypeError):
logger.warning(f"🔍 Invalid views value for {key_str}: {value_str}")
elif isinstance(views_data, list | tuple):
# Если это список [key1, value1, key2, value2]
for i in range(0, len(views_data), 2):
if i + 1 < len(views_data):
key = (
views_data[i].decode("utf-8")
if isinstance(views_data[i], bytes)
else str(views_data[i])
)
value = (
views_data[i + 1].decode("utf-8")
if isinstance(views_data[i + 1], bytes)
else str(views_data[i + 1])
)
# Пропускаем служебные ключи
if not key.startswith("_"):
try:
views_dict[key] = int(value)
except (ValueError, TypeError):
logger.warning(f"🔍 Invalid views value for {key}: {value}")
else:
logger.warning(f"🔍 Unexpected Redis data format: {type(views_data)}")
# Загружаем данные в класс
self.views_by_shout.update(views_dict)
logger.info("🔍 Loaded %d shouts with views from Redis", len(views_dict))
# Показываем образцы загруженных данных только если есть данные
if views_dict:
sample_items = list(views_dict.items())[:3]
logger.info("🔍 Sample loaded data: %s", sample_items)
else:
logger.debug("🔍 No valid views data found in Redis hash - views will be 0")
except Exception as e:
logger.warning(f"🔍 Error parsing Redis views data: {e} - views will be 0")
else:
logger.debug("🔍 Redis hash is empty for key: %s - views will be 0", latest_key)
# Выводим информацию о количестве загруженных записей
total_entries = await redis.execute("HGET", latest_key, "_total")
if total_entries:
@@ -201,22 +264,35 @@ class ViewedStorage:
"""
self = ViewedStorage
# 🔍 DEBUG: Логируем только если кеш пустой и это первый запрос
cache_size = len(self.views_by_shout)
if cache_size == 0 and shout_slug:
logger.debug(f"🔍 ViewedStorage cache is empty for slug '{shout_slug}'")
# 🔎 Используем только in-memory кеш для быстрого доступа
if shout_slug:
return self.views_by_shout.get(shout_slug, 0)
views = self.views_by_shout.get(shout_slug, 0)
if views > 0:
logger.debug(f"🔍 Found {views} views for slug '{shout_slug}'")
return views
# 🔎 Для ID ищем slug в БД и затем получаем views_count
if shout_id:
try:
with local_session() as session:
from orm.shout import Shout
shout = session.query(Shout).where(Shout.id == shout_id).first()
if shout and shout.slug:
return self.views_by_shout.get(shout.slug, 0)
views = self.views_by_shout.get(shout.slug, 0)
logger.debug(f"🔍 Found slug '{shout.slug}' for id {shout_id}, views: {views}")
return views
logger.debug(f"🔍 No shout found with id {shout_id} or missing slug")
except Exception as e:
logger.warning(f"Failed to get shout slug for id {shout_id}: {e}")
return 0
logger.debug("🔍 get_shout called without slug or id")
return 0
@staticmethod