From 64a728de412c6745369499009c48141f8bc29725 Mon Sep 17 00:00:00 2001 From: knst-kotov Date: Mon, 13 Dec 2021 21:05:00 +0300 Subject: [PATCH] add getTopicAuthors --- main.py | 3 ++- orm/shout.py | 43 +++++++++++++++++++++++++++++++++++++++++++ resolvers/topics.py | 14 +++++++++++++- schema.graphql | 1 + 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 438d838e..8cf9a788 100644 --- a/main.py +++ b/main.py @@ -15,7 +15,7 @@ from redis import redis from resolvers.base import resolvers from resolvers.zine import GitTask, ShoutsCache -from orm.shout import ShoutViewStorage, TopicStat +from orm.shout import ShoutViewStorage, TopicStat, ShoutAuthorStorage import asyncio @@ -33,6 +33,7 @@ async def start_up(): shouts_cache_task = asyncio.create_task(ShoutsCache.worker()) view_storage_task = asyncio.create_task(ShoutViewStorage.worker()) topic_stat_task = asyncio.create_task(TopicStat.worker()) + shout_author_task = asyncio.create_task(ShoutAuthorStorage.worker()) async def shutdown(): await redis.disconnect() diff --git a/orm/shout.py b/orm/shout.py index 2f7c46b3..0b84d787 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -158,6 +158,11 @@ class TopicStat: else: self.shouts_by_topic[topic] = [shout] + async def get_shouts(topic): + self = TopicStat + async with self.lock: + return self.shouts_by_topic.get(topic, []) + @staticmethod async def get_stat(topic): self = TopicStat @@ -186,6 +191,44 @@ class TopicStat: print("TopicStat worker: error = %s" % (err)) await asyncio.sleep(self.period) +class ShoutAuthorStorage: + authors_by_shout = {} + lock = asyncio.Lock() + + period = 30*60 #sec + + @staticmethod + async def load(session): + self = ShoutAuthorStorage + authors = session.query(ShoutAuthor) + for author in authors: + user = author.user + shout = author.shout + if shout in self.authors_by_shout: + self.authors_by_shout[shout].append(user) + else: + self.authors_by_shout[shout] = [user] + + @staticmethod + async def get_authors(shout): + self = ShoutAuthorStorage + async with self.lock: + return self.authors_by_shout.get(shout, []) + + @staticmethod + async def worker(): + self = ShoutAuthorStorage + print("ShoutAuthorStorage worker start") + while True: + try: + print("ShoutAuthorStorage worker: load stat") + with local_session() as session: + async with self.lock: + await self.load(session) + except Exception as err: + print("ShoutAuthorStorage worker: error = %s" % (err)) + await asyncio.sleep(self.period) + class Shout(Base): __tablename__ = 'shout' diff --git a/resolvers/topics.py b/resolvers/topics.py index 2b5b3f85..f551a1b0 100644 --- a/resolvers/topics.py +++ b/resolvers/topics.py @@ -1,5 +1,6 @@ from orm import Topic, TopicSubscription, TopicStorage, Shout, User -from orm.shout import TopicStat +from orm.shout import TopicStat, ShoutAuthorStorage +from orm.user import UserStorage from orm.base import local_session from resolvers.base import mutation, query, subscription from resolvers.zine import ShoutSubscriptions @@ -31,6 +32,17 @@ async def topics_by_author(_, info, author): slugs.update([topic.slug for topic in shout.topics]) return await TopicStorage.get_topics(slugs) +@query.field("getTopicAuthors") +async def topics_by_author(_, info, slug, count, page): + shouts = await TopicStat.get_shouts(slug) + authors = set() + for shout in shouts: + authors.update(await ShoutAuthorStorage.get_authors(shout)) + authors = list(authors) + authors.sort() #TODO sort by username + authors = authors[count * page : count * (page + 1) ] + return [await UserStorage.get_user(author) for author in authors] + @mutation.field("createTopic") @login_required async def create_topic(_, info, input): diff --git a/schema.graphql b/schema.graphql index 33ce98c8..631d014c 100644 --- a/schema.graphql +++ b/schema.graphql @@ -170,6 +170,7 @@ type Query { topicsBySlugs(slugs: [String]): [Topic]! topicsByCommunity(community: String!): [Topic]! topicsByAuthor(author: String!): [Topic]! + getTopicAuthors(slug: String!, count: Int!, page: Int!): [User]! # getOnlineUsers: [User!]!