following-fixes+fmt
All checks were successful
Deploy on push / deploy (push) Successful in 6s

This commit is contained in:
Untone 2024-11-02 12:09:24 +03:00
parent 09a6d085fd
commit 11611fd577
8 changed files with 73 additions and 81 deletions

View File

@ -52,7 +52,7 @@ class CacheRevalidationManager:
async def stop(self): async def stop(self):
"""Остановка фонового воркера.""" """Остановка фонового воркера."""
self.running = False self.running = False
if hasattr(self, 'task'): if hasattr(self, "task"):
self.task.cancel() self.task.cancel()
try: try:
await self.task await self.task

View File

@ -86,11 +86,7 @@ async def lifespan(app):
) )
yield yield
finally: finally:
tasks = [ tasks = [redis.disconnect(), ViewedStorage.stop(), revalidation_manager.stop()]
redis.disconnect(),
ViewedStorage.stop(),
revalidation_manager.stop()
]
await asyncio.gather(*tasks, return_exceptions=True) await asyncio.gather(*tasks, return_exceptions=True)

View File

@ -84,9 +84,10 @@ async def follow(_, info, what, slug):
logger.debug("Обновление кэша") logger.debug("Обновление кэша")
await cache_method(entity_dict) await cache_method(entity_dict)
if get_cached_follows_method: if get_cached_follows_method:
logger.debug("Получение обновленных подписок из кэша") logger.debug("Получение подписок из кэша")
follows = await get_cached_follows_method(follower_id) existing_follows = await get_cached_follows_method(follower_id)
# logger.debug(f"Текущие подписки: {follows}") follows = [*existing_follows, entity_dict]
logger.debug("Обновлен список подписок")
# Уведомление автора (только для типа AUTHOR) # Уведомление автора (только для типа AUTHOR)
if what == "AUTHOR": if what == "AUTHOR":
@ -97,7 +98,7 @@ async def follow(_, info, what, slug):
logger.exception("Произошла ошибка в функции 'follow'") logger.exception("Произошла ошибка в функции 'follow'")
return {"error": str(exc)} return {"error": str(exc)}
logger.debug(f"Функция 'follow' завершена успешно с результатом: {what.lower()}s={follows}") # logger.debug(f"Функция 'follow' завершена успешно с результатом: {what.lower()}s={follows}")
return {f"{what.lower()}s": follows} return {f"{what.lower()}s": follows}
@ -120,11 +121,7 @@ async def unfollow(_, info, what, slug):
"AUTHOR": (Author, AuthorFollower, get_cached_follower_authors, cache_author), "AUTHOR": (Author, AuthorFollower, get_cached_follower_authors, cache_author),
"TOPIC": (Topic, TopicFollower, get_cached_follower_topics, cache_topic), "TOPIC": (Topic, TopicFollower, get_cached_follower_topics, cache_topic),
"COMMUNITY": (Community, CommunityFollower, None, None), # Нет методов кэша для сообщества "COMMUNITY": (Community, CommunityFollower, None, None), # Нет методов кэша для сообщества
"SHOUT": ( "SHOUT": (Shout, ShoutReactionsFollower, None, None), # Нет методов кэша для shout
Shout,
ShoutReactionsFollower,
None,
), # Нет методов кэша для shout
} }
if what not in entity_classes: if what not in entity_classes:
@ -170,9 +167,10 @@ async def unfollow(_, info, what, slug):
logger.debug("Обновление кэша после отписки") logger.debug("Обновление кэша после отписки")
await cache_method(entity.dict()) await cache_method(entity.dict())
if get_cached_follows_method: if get_cached_follows_method:
logger.debug("Получение обновленных подписок из кэша") logger.debug("Получение подписок из кэша")
follows = await get_cached_follows_method(follower_id) existing_follows = await get_cached_follows_method(follower_id)
# logger.debug(f"Текущие подписки: {follows}") follows = filter(lambda x: x.id != entity_id, existing_follows)
logger.debug("Обновлен список подписок")
if what == "AUTHOR": if what == "AUTHOR":
logger.debug("Отправка уведомления автору об отписке") logger.debug("Отправка уведомления автору об отписке")
@ -181,10 +179,11 @@ async def unfollow(_, info, what, slug):
except Exception as exc: except Exception as exc:
logger.exception("Произошла ошибка в функции 'unfollow'") logger.exception("Произошла ошибка в функции 'unfollow'")
import traceback import traceback
traceback.print_exc() traceback.print_exc()
return {"error": str(exc)} return {"error": str(exc)}
logger.debug(f"Функция 'unfollow' завершена успешно с результатом: {entity_type}s={follows}, error={error}") # logger.debug(f"Функция 'unfollow' завершена успешно с результатом: {entity_type}s={follows}, error={error}")
return {f"{entity_type}s": follows, "error": error} return {f"{entity_type}s": follows, "error": error}
@ -211,9 +210,10 @@ def get_shout_followers(_, _info, slug: str = "", shout_id: int | None = None) -
except Exception as _exc: except Exception as _exc:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
logger.exception("Произошла ошибка в функции 'get_shout_followers'") logger.exception("Произошла ошибка в функции 'get_shout_followers'")
return [] return []
logger.debug(f"Функция 'get_shout_followers' завершена с {len(followers)} подписчиками") # logger.debug(f"Функция 'get_shout_followers' завершена с {len(followers)} подписчиками")
return followers return followers

View File

@ -70,11 +70,16 @@ def query_with_stat(info):
q = q.join(main_author, main_author.id == Shout.created_by) q = q.join(main_author, main_author.id == Shout.created_by)
q = q.add_columns( q = q.add_columns(
json_builder( json_builder(
"id", main_author.id, "id",
"name", main_author.name, main_author.id,
"slug", main_author.slug, "name",
"pic", main_author.pic, main_author.name,
"created_at", main_author.created_at "slug",
main_author.slug,
"pic",
main_author.pic,
"created_at",
main_author.created_at,
).label("main_author") ).label("main_author")
) )
@ -85,10 +90,7 @@ def query_with_stat(info):
q = q.join(main_topic, main_topic.id == main_topic_join.topic) q = q.join(main_topic, main_topic.id == main_topic_join.topic)
q = q.add_columns( q = q.add_columns(
json_builder( json_builder(
"id", main_topic.id, "id", main_topic.id, "title", main_topic.title, "slug", main_topic.slug, "is_main", main_topic_join.main
"title", main_topic.title,
"slug", main_topic.slug,
"is_main", main_topic_join.main
).label("main_topic") ).label("main_topic")
) )
@ -97,13 +99,8 @@ def query_with_stat(info):
select( select(
ShoutTopic.shout, ShoutTopic.shout,
json_array_builder( json_array_builder(
json_builder( json_builder("id", Topic.id, "title", Topic.title, "slug", Topic.slug, "is_main", ShoutTopic.main)
"id", Topic.id, ).label("topics"),
"title", Topic.title,
"slug", Topic.slug,
"is_main", ShoutTopic.main
)
).label("topics")
) )
.outerjoin(Topic, ShoutTopic.topic == Topic.id) .outerjoin(Topic, ShoutTopic.topic == Topic.id)
.where(ShoutTopic.shout == Shout.id) .where(ShoutTopic.shout == Shout.id)
@ -119,14 +116,20 @@ def query_with_stat(info):
ShoutAuthor.shout, ShoutAuthor.shout,
json_array_builder( json_array_builder(
json_builder( json_builder(
"id", Author.id, "id",
"name", Author.name, Author.id,
"slug", Author.slug, "name",
"pic", Author.pic, Author.name,
"caption", ShoutAuthor.caption, "slug",
"created_at", Author.created_at Author.slug,
"pic",
Author.pic,
"caption",
ShoutAuthor.caption,
"created_at",
Author.created_at,
) )
).label("authors") ).label("authors"),
) )
.outerjoin(Author, ShoutAuthor.author == Author.id) .outerjoin(Author, ShoutAuthor.author == Author.id)
.where(ShoutAuthor.shout == Shout.id) .where(ShoutAuthor.shout == Shout.id)
@ -147,12 +150,12 @@ def query_with_stat(info):
case( case(
(Reaction.kind == ReactionKind.LIKE.value, 1), (Reaction.kind == ReactionKind.LIKE.value, 1),
(Reaction.kind == ReactionKind.DISLIKE.value, -1), (Reaction.kind == ReactionKind.DISLIKE.value, -1),
else_=0 else_=0,
) )
).filter(Reaction.reply_to.is_(None)).label("rating"), )
func.max(Reaction.created_at).filter( .filter(Reaction.reply_to.is_(None))
Reaction.reply_to.is_(None) .label("rating"),
).label("last_reacted_at") func.max(Reaction.created_at).filter(Reaction.reply_to.is_(None)).label("last_reacted_at"),
) )
.where(Reaction.deleted_at.is_(None)) .where(Reaction.deleted_at.is_(None))
.group_by(Reaction.shout) .group_by(Reaction.shout)
@ -162,9 +165,12 @@ def query_with_stat(info):
q = q.outerjoin(stats_subquery, stats_subquery.c.shout == Shout.id) q = q.outerjoin(stats_subquery, stats_subquery.c.shout == Shout.id)
q = q.add_columns( q = q.add_columns(
json_builder( json_builder(
"comments_count", stats_subquery.c.comments_count, "comments_count",
"rating", stats_subquery.c.rating, stats_subquery.c.comments_count,
"last_reacted_at", stats_subquery.c.last_reacted_at, "rating",
stats_subquery.c.rating,
"last_reacted_at",
stats_subquery.c.last_reacted_at,
).label("stat") ).label("stat")
) )
@ -223,16 +229,16 @@ def get_shouts_with_links(info, q, limit=20, offset=0):
elif isinstance(row.stat, dict): elif isinstance(row.stat, dict):
stat = row.stat stat = row.stat
viewed = ViewedStorage.get_shout(shout_id=shout_id) or 0 viewed = ViewedStorage.get_shout(shout_id=shout_id) or 0
shout_dict["stat"] = { shout_dict["stat"] = {**stat, "viewed": viewed, "commented": stat.get("comments_count", 0)}
**stat,
"viewed": viewed,
"commented": stat.get("comments_count", 0)
}
if has_field(info, "main_topic") and hasattr(row, "main_topic"): if has_field(info, "main_topic") and hasattr(row, "main_topic"):
shout_dict["main_topic"] = json.loads(row.main_topic) if isinstance(row.stat, str) else row.main_topic shout_dict["main_topic"] = (
json.loads(row.main_topic) if isinstance(row.stat, str) else row.main_topic
)
if has_field(info, "authors") and hasattr(row, "authors"): if has_field(info, "authors") and hasattr(row, "authors"):
shout_dict["authors"] = json.loads(row.authors) if isinstance(row.authors, str) else row.authors shout_dict["authors"] = (
json.loads(row.authors) if isinstance(row.authors, str) else row.authors
)
if has_field(info, "topics") and hasattr(row, "topics"): if has_field(info, "topics") and hasattr(row, "topics"):
shout_dict["topics"] = json.loads(row.topics) if isinstance(row.topics, str) else row.topics shout_dict["topics"] = json.loads(row.topics) if isinstance(row.topics, str) else row.topics
@ -321,15 +327,11 @@ def apply_sorting(q, options):
order_str = options.get("order_by") order_str = options.get("order_by")
if order_str in ["rating", "comments_count", "last_reacted_at"]: if order_str in ["rating", "comments_count", "last_reacted_at"]:
query_order_by = desc(text(order_str)) if options.get("order_by_desc", True) else asc(text(order_str)) query_order_by = desc(text(order_str)) if options.get("order_by_desc", True) else asc(text(order_str))
q = ( q = q.distinct(text(order_str), Shout.id).order_by( # DISTINCT ON включает поле сортировки
q.distinct(text(order_str), Shout.id) # DISTINCT ON включает поле сортировки nulls_last(query_order_by), Shout.id
.order_by(nulls_last(query_order_by), Shout.id)
) )
else: else:
q = ( q = q.distinct(Shout.published_at, Shout.id).order_by(Shout.published_at.desc(), Shout.id)
q.distinct(Shout.published_at, Shout.id)
.order_by(Shout.published_at.desc(), Shout.id)
)
return q return q

View File

@ -5,7 +5,6 @@ from granian.server import Granian
from settings import PORT from settings import PORT
from utils.logger import root_logger as logger from utils.logger import root_logger as logger
if __name__ == "__main__": if __name__ == "__main__":
logger.info("started") logger.info("started")

View File

@ -25,8 +25,8 @@ if DB_URL.startswith("postgres"):
pool_pre_ping=True, # Добавить проверку соединений pool_pre_ping=True, # Добавить проверку соединений
connect_args={ connect_args={
"sslmode": "disable", "sslmode": "disable",
"connect_timeout": 40 # Добавить таймаут подключения "connect_timeout": 40, # Добавить таймаут подключения
} },
) )
else: else:
engine = create_engine(DB_URL, echo=False, connect_args={"check_same_thread": False}) engine = create_engine(DB_URL, echo=False, connect_args={"check_same_thread": False})

View File

@ -168,12 +168,7 @@ class SearchService:
if self.client: if self.client:
try: try:
await asyncio.wait_for( await asyncio.wait_for(
self.client.index( self.client.index(index=self.index_name, id=str(shout.id), body=index_body), timeout=40.0
index=self.index_name,
id=str(shout.id),
body=index_body
),
timeout=40.0
) )
except asyncio.TimeoutError: except asyncio.TimeoutError:
logger.error(f"Indexing timeout for shout {shout.id}") logger.error(f"Indexing timeout for shout {shout.id}")