diff --git a/orm/__init__.py b/orm/__init__.py index f7c61801..076972ec 100644 --- a/orm/__init__.py +++ b/orm/__init__.py @@ -2,7 +2,7 @@ from orm.rbac import Operation, Resource, Permission, Role, RoleStorage from orm.community import Community from orm.user import User, UserRating, UserRole, UserStorage from orm.message import Message -from orm.topic import Topic, TopicSubscription +from orm.topic import Topic, TopicSubscription, TopicStorage from orm.notification import Notification from orm.shout import Shout, ShoutAuthor, ShoutTopic, ShoutRating, ShoutViewByDay,\ ShoutRatingStorage, ShoutViewStorage @@ -23,3 +23,4 @@ with local_session() as session: ShoutViewStorage.init(session) RoleStorage.init(session) UserStorage.init(session) + TopicStorage.init(session) diff --git a/orm/topic.py b/orm/topic.py index 4ecc337e..d9e6668e 100644 --- a/orm/topic.py +++ b/orm/topic.py @@ -3,6 +3,8 @@ from sqlalchemy import Table, Column, Integer, String, ForeignKey, DateTime, JSO from sqlalchemy.orm import relationship from orm.base import Base +import asyncio + class TopicSubscription(Base): __tablename__ = "topic_subscription" @@ -22,3 +24,48 @@ class Topic(Base): pic: str = Column(String, nullable=True, comment="Picture") children = Column(JSONType, nullable=True, comment="list of children topics") community = Column(ForeignKey("community.slug"), nullable=False, comment="Community") + +class TopicStorage: + topics = {} + lock = asyncio.Lock() + + @staticmethod + def init(session): + self = TopicStorage + topics = session.query(Topic) + self.topics = dict([(topic.slug, topic) for topic in topics]) + for topic in self.topics.values(): + self.load_parents(topic) + + @staticmethod + def load_parents(topic): + self = TopicStorage + parents = [] + for parent in self.topics.values(): + if topic.slug in parent.children: + parents.append(parent.slug) + topic.parents = parents + return topic + + @staticmethod + async def get_topics(slugs): + self = TopicStorage + async with self.lock: + if not slugs: + return self.topics.values() + topics = filter(lambda topic: topic.slug in slugs, self.topics.values()) + return list(topics) + + @staticmethod + async def get_topics_by_community(community): + self = TopicStorage + async with self.lock: + topics = filter(lambda topic: topic.community == community, self.topics.values()) + return list(topics) + + @staticmethod + async def add_topic(topic): + self = TopicStorage + async with self.lock: + self.topics[topic.slug] = topic + self.load_parents(topic) diff --git a/resolvers/__init__.py b/resolvers/__init__.py index d8352521..913d899f 100644 --- a/resolvers/__init__.py +++ b/resolvers/__init__.py @@ -4,7 +4,7 @@ from resolvers.zine import create_shout, get_shout_by_slug, top_month, top_overa recent_shouts, top_authors, top_viewed from resolvers.profile import get_users_by_slugs, get_current_user from resolvers.topics import topic_subscribe, topic_unsubscribe, topics_by_author, \ - topics_by_community, topics_by_slugs, topics_all + topics_by_community, topics_by_slugs from resolvers.comments import create_comment from resolvers.community import create_community, delete_community, get_community, get_communities @@ -27,7 +27,6 @@ __all__ = [ "top_month", "top_overall", "top_viewed", - "topics_all", "topics_by_slugs", "topics_by_community", "topics_by_author", diff --git a/resolvers/topics.py b/resolvers/topics.py index be875e17..95729edb 100644 --- a/resolvers/topics.py +++ b/resolvers/topics.py @@ -1,41 +1,29 @@ -from orm import Topic, TopicSubscription, Shout, User +from orm import Topic, TopicSubscription, TopicStorage, Shout, User from orm.base import local_session from resolvers.base import mutation, query, subscription from resolvers.zine import ShoutSubscriptions from auth.authenticate import login_required import asyncio - -@query.field("topicsAll") -async def topics_all(_, info): - topics = [] - with local_session() as session: - topics = session.query(Topic) - return topics - @query.field("topicsBySlugs") -async def topics_by_slugs(_, info, slugs): - topics = [] +async def topics_by_slugs(_, info, slugs = None): with local_session() as session: - topics = session.query(Topic).filter(Topic.slug.in_(slugs)) - return topics + return await TopicStorage.get_topics(slugs) @query.field("topicsByCommunity") async def topics_by_community(_, info, community): - topics = [] with local_session() as session: - topics = session.query(Topic).filter(Topic.community == community) - return topics + return await TopicStorage.get_topics_by_community(community) @query.field("topicsByAuthor") async def topics_by_author(_, info, author): - topics = {} + slugs = set() with local_session() as session: shouts = session.query(Shout).\ filter(Shout.authors.any(User.slug == author)) for shout in shouts: - topics.update(dict([(topic.slug, topic) for topic in shout.topics])) - return topics.values() + slugs.update([topic.slug for topic in shout.topics]) + return await TopicStorage.get_topics(slugs) @mutation.field("topicSubscribe") @login_required diff --git a/schema.graphql b/schema.graphql index 18c7816f..ea552d69 100644 --- a/schema.graphql +++ b/schema.graphql @@ -151,8 +151,7 @@ type Query { topAuthors(limit: Int): [User]! # topics - topicsAll: [Topic]! - topicsBySlugs(slugs: [String]!): [Topic]! + topicsBySlugs(slugs: [String]): [Topic]! topicsByCommunity(community: String!): [Topic]! topicsByAuthor(author: String!): [Topic]!