semaphore
Some checks failed
Deploy on push / deploy (push) Failing after 9s

This commit is contained in:
Untone 2024-08-06 18:57:35 +03:00
parent b823862cec
commit 95977f0853

View File

@ -1,7 +1,5 @@
import asyncio import asyncio
from sqlalchemy import event, select from sqlalchemy import event, select
from orm.author import Author, AuthorFollower from orm.author import Author, AuthorFollower
from orm.reaction import Reaction from orm.reaction import Reaction
from orm.shout import Shout, ShoutAuthor from orm.shout import Shout, ShoutAuthor
@ -16,17 +14,15 @@ DEFAULT_FOLLOWS = {
"communities": [{"id": 1, "name": "Дискурс", "slug": "discours", "pic": ""}], "communities": [{"id": 1, "name": "Дискурс", "slug": "discours", "pic": ""}],
} }
# Limit the number of concurrent tasks
def run_background_task(coro): semaphore = asyncio.Semaphore(10)
"""Запускает асинхронную задачу в фоне и обрабатывает исключения."""
task = asyncio.create_task(coro)
task.add_done_callback(handle_task_result)
def handle_task_result(task): async def run_background_task(coro):
"""Обработка результата завершенной задачи.""" """Runs an asynchronous task in the background with concurrency control."""
async with semaphore:
try: try:
task.result() await coro
except Exception as e: except Exception as e:
logger.error(f"Error in background task: {e}") logger.error(f"Error in background task: {e}")
@ -47,8 +43,8 @@ async def handle_author_follower_change(author_id: int, follower_id: int, is_ins
follower = follower_result[0] follower = follower_result[0]
if author_with_stat: if author_with_stat:
author_dict = author_with_stat.dict() author_dict = author_with_stat.dict()
run_background_task(cache_author(author_dict)) await run_background_task(cache_author(author_dict))
run_background_task(cache_follows(follower.id, "author", author_with_stat.id, is_insert)) await run_background_task(cache_follows(follower.id, "author", author_with_stat.id, is_insert))
async def handle_topic_follower_change(topic_id: int, follower_id: int, is_insert: bool): async def handle_topic_follower_change(topic_id: int, follower_id: int, is_insert: bool):
@ -65,24 +61,22 @@ async def handle_topic_follower_change(topic_id: int, follower_id: int, is_inser
if isinstance(follower[0], Author) and isinstance(topic[0], Topic): if isinstance(follower[0], Author) and isinstance(topic[0], Topic):
topic = topic[0] topic = topic[0]
follower = follower[0] follower = follower[0]
run_background_task(cache_topic(topic.dict())) await run_background_task(cache_topic(topic.dict()))
run_background_task(cache_author(follower.dict())) await run_background_task(cache_author(follower.dict()))
run_background_task(cache_follows(follower.id, "topic", topic.id, is_insert)) await run_background_task(cache_follows(follower.id, "topic", topic.id, is_insert))
async def after_shout_update(_mapper, _connection, shout: Shout): async def after_shout_update(_mapper, _connection, shout: Shout):
logger.info("after shout update") logger.info("after shout update")
authors_query = ( authors_query = (
select(Author) select(Author).join(ShoutAuthor, ShoutAuthor.author == Author.id).filter(ShoutAuthor.shout == shout.id)
.join(ShoutAuthor, ShoutAuthor.author == Author.id) # Use join directly with Author
.filter(ShoutAuthor.shout == shout.id)
) )
authors_updated = await get_with_stat(authors_query) authors_updated = await get_with_stat(authors_query)
for author_with_stat in authors_updated: tasks = [run_background_task(cache_author(author_with_stat.dict())) for author_with_stat in authors_updated]
run_background_task(cache_author(author_with_stat.dict())) await asyncio.gather(*tasks)
async def after_reaction_update(mapper, connection, reaction: Reaction): async def after_reaction_update(mapper, connection, reaction: Reaction):
@ -90,13 +84,15 @@ async def after_reaction_update(mapper, connection, reaction: Reaction):
try: try:
# reaction author # reaction author
author_subquery = select(Author).where(Author.id == reaction.created_by) author_subquery = select(Author).where(Author.id == reaction.created_by)
result = await get_with_stat(author_subquery) result = await get_with_stat(author_subquery)
tasks = []
if result: if result:
author_with_stat = result[0] author_with_stat = result[0]
if isinstance(author_with_stat, Author): if isinstance(author_with_stat, Author):
author_dict = author_with_stat.dict() author_dict = author_with_stat.dict()
run_background_task(cache_author(author_dict)) tasks.append(run_background_task(cache_author(author_dict)))
# reaction repliers # reaction repliers
replied_author_subquery = ( replied_author_subquery = (
@ -104,13 +100,15 @@ async def after_reaction_update(mapper, connection, reaction: Reaction):
) )
authors_with_stat = await get_with_stat(replied_author_subquery) authors_with_stat = await get_with_stat(replied_author_subquery)
for author_with_stat in authors_with_stat: for author_with_stat in authors_with_stat:
run_background_task(cache_author(author_with_stat.dict())) tasks.append(run_background_task(cache_author(author_with_stat.dict())))
shout_query = select(Shout).where(Shout.id == reaction.shout) shout_query = select(Shout).where(Shout.id == reaction.shout)
shout_result = await connection.execute(shout_query) shout_result = await connection.execute(shout_query)
shout = shout_result.scalar_one_or_none() shout = shout_result.scalar_one_or_none()
if shout: if shout:
await after_shout_update(mapper, connection, shout) tasks.append(after_shout_update(mapper, connection, shout))
await asyncio.gather(*tasks)
except Exception as exc: except Exception as exc:
logger.error(exc) logger.error(exc)
import traceback import traceback
@ -125,27 +123,27 @@ async def after_author_update(_mapper, _connection, author: Author):
if result: if result:
author_with_stat = result[0] author_with_stat = result[0]
author_dict = author_with_stat.dict() author_dict = author_with_stat.dict()
run_background_task(cache_author(author_dict)) await run_background_task(cache_author(author_dict))
async def after_topic_follower_insert(_mapper, _connection, target: TopicFollower): async def after_topic_follower_insert(_mapper, _connection, target: TopicFollower):
logger.info(target) logger.info(target)
run_background_task(handle_topic_follower_change(target.topic, target.follower, True)) await run_background_task(handle_topic_follower_change(target.topic, target.follower, True))
async def after_topic_follower_delete(_mapper, _connection, target: TopicFollower): async def after_topic_follower_delete(_mapper, _connection, target: TopicFollower):
logger.info(target) logger.info(target)
run_background_task(handle_topic_follower_change(target.topic, target.follower, False)) await run_background_task(handle_topic_follower_change(target.topic, target.follower, False))
async def after_author_follower_insert(_mapper, _connection, target: AuthorFollower): async def after_author_follower_insert(_mapper, _connection, target: AuthorFollower):
logger.info(target) logger.info(target)
run_background_task(handle_author_follower_change(target.author, target.follower, True)) await run_background_task(handle_author_follower_change(target.author, target.follower, True))
async def after_author_follower_delete(_mapper, _connection, target: AuthorFollower): async def after_author_follower_delete(_mapper, _connection, target: AuthorFollower):
logger.info(target) logger.info(target)
run_background_task(handle_author_follower_change(target.author, target.follower, False)) await run_background_task(handle_author_follower_change(target.author, target.follower, False))
def events_register(): def events_register():