diff --git a/resolvers/__init__.py b/resolvers/__init__.py index 3e3e2710..fdb913bf 100644 --- a/resolvers/__init__.py +++ b/resolvers/__init__.py @@ -1,6 +1,8 @@ from resolvers.author import ( get_author, get_author_follows, + get_author_follows_topics, + get_author_follows_authors, get_author_followers, get_author_id, get_authors_all, @@ -45,6 +47,8 @@ __all__ = [ 'get_author', 'get_author_id', 'get_author_follows', + 'get_author_follows_topics', + 'get_author_follows_authors', 'get_authors_all', 'load_authors_by', 'rate_author', diff --git a/resolvers/author.py b/resolvers/author.py index 51d72d4b..970eb39d 100644 --- a/resolvers/author.py +++ b/resolvers/author.py @@ -9,7 +9,7 @@ from orm.reaction import Reaction, ReactionKind from orm.shout import Shout, ShoutAuthor, ShoutTopic from orm.topic import Topic from resolvers.follower import query_follows -from resolvers.stat import get_authors_with_stat, execute_with_ministat +from resolvers.stat import get_authors_with_stat, execute_with_ministat, author_follows_authors, author_follows_topics from services.auth import login_required from services.db import local_session from services.rediscache import redis @@ -210,15 +210,36 @@ def load_authors_by(_, _info, by, limit, offset): @query.field('get_author_follows') def get_author_follows(_, _info, slug='', user=None, author_id=None): with local_session() as session: - if not user and (author_id or slug): - user_query_result = ( - session.query(Author.user) - .where(or_(Author.id == author_id, Author.slug == slug)) - .first() - ) - user = user_query_result[0] if user_query_result else None - if user: - follows = query_follows(user) + if user or slug: + author_id_result = session.query(Author.id).filter(or_(Author.user == user, Author.slug == slug)).first() + author_id = author_id_result[0] if author_id_result else None + if author_id: + follows = query_follows(author_id) + return follows + else: + raise ValueError('Author not found') + +@query.field('get_author_follows_topics') +def get_author_follows_topics(_, _info, slug='', user=None, author_id=None): + with local_session() as session: + if user or slug: + author_id_result = session.query(Author.id).filter(or_(Author.user == user, Author.slug == slug)).first() + author_id = author_id_result[0] if author_id_result else None + if author_id: + follows = author_follows_authors(author_id) + return follows + else: + raise ValueError('Author not found') + + +@query.field('get_author_follows_authors') +def get_author_follows_authors(_, _info, slug='', user=None, author_id=None): + with local_session() as session: + if user or slug: + author_id_result = session.query(Author.id).filter(or_(Author.user == user, Author.slug == slug)).first() + author_id = author_id_result[0] if author_id_result else None + if author_id: + follows = author_follows_topics(author_id) return follows else: raise ValueError('Author not found') diff --git a/resolvers/follower.py b/resolvers/follower.py index ff0a8b6a..169e8365 100644 --- a/resolvers/follower.py +++ b/resolvers/follower.py @@ -91,7 +91,8 @@ async def get_follows_by_user_id(user_id: str): follows = DEFAULT_FOLLOWS day_old = int(time.time()) - author.get('last_seen', 0) > 24 * 60 * 60 if day_old: - follows = query_follows(user_id) + author_id = json.loads(str(author)).get('id') + follows = query_follows(author_id) else: logger.debug(f'getting follows for {user_id} from redis') res = await redis.execute('GET', f'user:{user_id}:follows') diff --git a/resolvers/stat.py b/resolvers/stat.py index de2e5cf6..5f7bab38 100644 --- a/resolvers/stat.py +++ b/resolvers/stat.py @@ -5,6 +5,7 @@ from orm.topic import TopicFollower, Topic from services.db import local_session from orm.author import AuthorFollower, Author from orm.shout import ShoutTopic, ShoutAuthor +from services.logger import root_logger as logger def add_topic_stat_columns(q): @@ -90,40 +91,42 @@ def get_topics_with_stat(q): return execute_with_ministat(q) -def query_follows(author_id: int): +def author_follows_authors(author_id: int): + aliased_shout_authors = aliased(ShoutAuthor) subquery_shout_author = ( select( [ - ShoutAuthor.author, - func.count(distinct(ShoutAuthor.shout)).label('shouts_stat'), + aliased_shout_authors.author, + func.count(distinct(aliased_shout_authors.shout)).label('shouts_stat'), ] ) - .group_by(ShoutAuthor.author) - .where(ShoutAuthor.author == author_id) + .group_by(aliased_shout_authors.author) + .where(aliased_shout_authors.author == author_id) .alias() ) - + alias_author_authors = aliased(AuthorFollower) subquery_author_authors = ( select( [ - AuthorFollower.author, - func.count(distinct(AuthorFollower.author)).label('authors_stat'), + alias_author_authors.author, + func.count(distinct(alias_author_authors.author)).label('authors_stat'), ] ) - .group_by(AuthorFollower.author) - .where(AuthorFollower.author == author_id) + .group_by(alias_author_authors.author) + .where(alias_author_authors.follower == author_id) .alias() ) + alias_author_followers = aliased(AuthorFollower) subquery_author_followers = ( select( [ - AuthorFollower.follower, - func.count(distinct(AuthorFollower.follower)).label('followers_stat'), + alias_author_followers.follower, + func.count(distinct(alias_author_followers.follower)).label('followers_stat'), ] ) - .group_by(AuthorFollower.follower) - .where(AuthorFollower.follower == author_id) + .group_by(alias_author_followers.follower) + .where(alias_author_followers.author == author_id) .alias() ) @@ -138,7 +141,7 @@ def query_follows(author_id: int): authors_query = ( select( [ - Author.id, + Author, subq_shout_author_alias.shouts_stat, subq_author_authors_alias.authors_stat, subq_author_followers_alias.followers_stat, @@ -159,6 +162,10 @@ def query_follows(author_id: int): authors = execute_with_ministat(authors_query) + return authors + + +def author_follows_topics(author_id: int): subquery_shout_topic = ( select( [ @@ -203,7 +210,7 @@ def query_follows(author_id: int): topics_query = ( select( [ - Topic.id, + Topic, subq_shout_topic_alias.columns.shouts_stat, subq_shout_topic_authors_alias.columns.authors_stat, subq_topic_followers_alias.columns.followers_stat, @@ -224,9 +231,18 @@ def query_follows(author_id: int): ) topics = execute_with_ministat(topics_query) + return topics - return { - 'topics': topics, - 'authors': authors, - 'communities': [{'id': 1, 'name': 'Дискурс', 'slug': 'discours'}], - } + +def query_follows(author_id: int): + try: + topics = author_follows_topics(author_id) + authors = author_follows_authors(author_id) + return { + 'topics': topics, + 'authors': authors, + 'communities': [{'id': 1, 'name': 'Дискурс', 'slug': 'discours'}], + } + except Exception as e: + logger.exception(f"An error occurred while executing query_follows: {e}") + raise Exception("An error occurred while executing query_follows") from e diff --git a/schema/query.graphql b/schema/query.graphql index 9acdf216..3a6ede1f 100644 --- a/schema/query.graphql +++ b/schema/query.graphql @@ -17,6 +17,8 @@ type Query { get_topic_followers(slug: String, topic_id: Int): [Author] get_author_followers(slug: String, user: String, author_id: Int): [Author] get_author_follows(slug: String, user: String, author_id: Int): AuthorFollows! + get_author_follows_topics(slug: String, user: String, author_id: Int): [Topic] + get_author_follows_authors(slug: String, user: String, author_id: Int): [Author] load_shouts_followed(follower_id: Int!, limit: Int, offset: Int): [Shout] # userReactedShouts # reaction