fmt
All checks were successful
Deploy on push / deploy (push) Successful in 58s

This commit is contained in:
Untone 2025-02-04 15:27:59 +03:00
parent 56db33d7f1
commit dce05342df
3 changed files with 45 additions and 46 deletions

3
.gitignore vendored
View File

@ -159,4 +159,5 @@ dokku_config
views.json views.json
*.pem *.pem
*.key *.key
*.crt *.crt
*cache.json

View File

@ -1,4 +1,4 @@
#### [0.4.8] #### [0.4.8] - 2025-02-03
- `Reaction.deleted_at` filter on `update_reaction` resolver added - `Reaction.deleted_at` filter on `update_reaction` resolver added
- `triggers` module updated with `after_shout_handler`, `after_reaction_handler` for cache revalidation - `triggers` module updated with `after_shout_handler`, `after_reaction_handler` for cache revalidation
- `after_shout_handler`, `after_reaction_handler` now also handle `deleted_at` field - `after_shout_handler`, `after_reaction_handler` now also handle `deleted_at` field

86
cache/cache.py vendored
View File

@ -156,43 +156,37 @@ async def get_cached_authors_by_ids(author_ids: List[int]) -> List[dict]:
async def get_cached_topic_followers(topic_id: int): async def get_cached_topic_followers(topic_id: int):
""" """
Получает подписчиков темы по ID, используя кеш Redis. Получает подписчиков темы по ID, используя кеш Redis.
Если данные отсутствуют в кеше, извлекает из базы данных и кеширует их.
Args: Args:
topic_id: Идентификатор темы, подписчиков которой необходимо получить. topic_id: ID темы
Returns: Returns:
List[dict]: Список подписчиков темы, каждый элемент представляет собой словарь с данными автора. List[dict]: Список подписчиков с их данными
""" """
try: try:
# Попытка получить данные из кеша cache_key = CACHE_KEYS["TOPIC_FOLLOWERS"].format(topic_id)
cached = await redis_operation("GET", f"topic:followers:{topic_id}") cached = await redis_operation("GET", cache_key)
if cached: if cached:
followers_ids = json.loads(cached) followers_ids = json.loads(cached)
logger.debug(f"Cached {len(followers_ids)} followers for topic #{topic_id}") logger.debug(f"Found {len(followers_ids)} cached followers for topic #{topic_id}")
followers = await get_cached_authors_by_ids(followers_ids) return await get_cached_authors_by_ids(followers_ids)
return followers
# Если данные не найдены в кеше, загрузка из базы данных
with local_session() as session: with local_session() as session:
result = ( followers_ids = [
session.query(Author.id) f[0] for f in session.query(Author.id)
.join(TopicFollower, TopicFollower.follower == Author.id) .join(TopicFollower, TopicFollower.follower == Author.id)
.filter(TopicFollower.topic == topic_id) .filter(TopicFollower.topic == topic_id)
.all() .all()
) ]
followers_ids = [f[0] for f in result]
await redis_operation("SETEX", cache_key, value=json.dumps(followers_ids), ttl=CACHE_TTL)
# Кэширование результатов
await redis_operation("SET", f"topic:followers:{topic_id}", json.dumps(followers_ids))
# Получение подробной информации о подписчиках по их ID
followers = await get_cached_authors_by_ids(followers_ids) followers = await get_cached_authors_by_ids(followers_ids)
logger.debug(f"Topic#{topic_id} followers fetched and cached: {len(followers)} followers found.") logger.debug(f"Cached {len(followers)} followers for topic #{topic_id}")
return followers return followers
except Exception as e: except Exception as e:
logger.error(f"Ошибка при получении подписчиков для темы #{topic_id}: {str(e)}") logger.error(f"Error getting followers for topic #{topic_id}: {str(e)}")
return [] return []
@ -410,34 +404,38 @@ async def cache_related_entities(shout: Shout):
async def invalidate_shout_related_cache(shout: Shout, author_id: int): async def invalidate_shout_related_cache(shout: Shout, author_id: int):
""" """
Инвалидирует весь кэш, связанный с публикацией Инвалидирует весь кэш, связанный с публикацией и её связями
Args:
shout: Объект публикации
author_id: ID автора
""" """
# Базовые ленты cache_keys = {
cache_keys = [
"feed", # основная лента "feed", # основная лента
f"author_{author_id}", # публикации автора f"author_{author_id}", # публикации автора
"random_top", # случайные топовые "random_top", # случайные топовые
"unrated", # неоцененные "unrated", # неоцененные
"recent", # последние публикации "recent", # последние
"coauthored", # совместные публикации "coauthored", # совместные
f"authored_{author_id}", # авторские публикации }
f"followed_{author_id}", # подписки автора
] # Добавляем ключи авторов
cache_keys.update(
f"author_{a.id}" for a in shout.authors
)
cache_keys.update(
f"authored_{a.id}" for a in shout.authors
)
# Добавляем ключи тем
cache_keys.update(
f"topic_{t.id}" for t in shout.topics
)
cache_keys.update(
f"topic_shouts_{t.id}" for t in shout.topics
)
# Добавляем ключи для всех авторов публикации await invalidate_shouts_cache(list(cache_keys))
for author in shout.authors:
cache_keys.extend(
[f"author_{author.id}", f"authored_{author.id}", f"followed_{author.id}", f"coauthored_{author.id}"]
)
# Добавляем ключи для тем
for topic in shout.topics:
cache_keys.extend(
[f"topic_{topic.id}", f"topic_shouts_{topic.id}", f"topic_recent_{topic.id}", f"topic_top_{topic.id}"]
)
# Инвалидируем все ключи
await invalidate_shouts_cache(cache_keys)
async def redis_operation(operation: str, key: str, value=None, ttl=None): async def redis_operation(operation: str, key: str, value=None, ttl=None):