From 26e903d4f2df87fb886de287dabd348c7a18ed28 Mon Sep 17 00:00:00 2001 From: knst-kotov Date: Fri, 17 Dec 2021 11:22:31 +0100 Subject: [PATCH] add shout stat --- main.py | 3 ++- orm/shout.py | 45 ++++++++++++++++++++++++++++++++++++++++++++- resolvers/zine.py | 4 ---- schema.graphql | 10 ++++++++-- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index bf695d55..34ef8948 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, ShoutAuthorStorage +from orm.shout import ShoutViewStorage, TopicStat, ShoutAuthorStorage, CommentStat import asyncio @@ -34,6 +34,7 @@ async def start_up(): view_storage_task = asyncio.create_task(ShoutViewStorage.worker()) shout_author_task = asyncio.create_task(ShoutAuthorStorage.worker()) topic_stat_task = asyncio.create_task(TopicStat.worker()) + comment_stat_task = asyncio.create_task(CommentStat.worker()) async def shutdown(): await redis.disconnect() diff --git a/orm/shout.py b/orm/shout.py index 69dde280..638bab24 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -1,6 +1,6 @@ from typing import List from datetime import datetime, timedelta -from sqlalchemy import Table, Column, Integer, String, ForeignKey, DateTime, Boolean +from sqlalchemy import Table, Column, Integer, String, ForeignKey, DateTime, Boolean, func from sqlalchemy.orm import relationship from sqlalchemy.orm.attributes import flag_modified from orm import Permission, User, Topic, TopicSubscription @@ -204,6 +204,7 @@ class TopicStat: else: self.subs_by_topic[topic] = [user] + @staticmethod async def get_shouts(topic): self = TopicStat async with self.lock: @@ -277,6 +278,40 @@ class ShoutAuthorStorage: print("ShoutAuthorStorage worker: error = %s" % (err)) await asyncio.sleep(self.period) +class CommentStat: + stat_by_topic = {} + lock = asyncio.Lock() + + period = 30*60 #sec + + @staticmethod + async def load(session): + self = CommentStat + + stats = session.query(Comment.shout, func.count(Comment.id).label("count")).\ + group_by(Comment.shout) + self.stat_by_topic = dict([(stat.shout, stat.count) for stat in stats]) + + @staticmethod + async def get_stat(shout): + self = CommentStat + async with self.lock: + return self.stat_by_topic.get(shout, 0) + + @staticmethod + async def worker(): + self = CommentStat + print("CommentStat worker start") + while True: + try: + print("CommentStat worker: load stat") + with local_session() as session: + async with self.lock: + await self.load(session) + except Exception as err: + print("CommentStat worker: error = %s" % (err)) + await asyncio.sleep(self.period) + class Shout(Base): __tablename__ = 'shout' @@ -301,3 +336,11 @@ class Shout(Base): topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) mainTopic = Column(ForeignKey("topic.slug"), nullable=True) visibleFor = relationship(lambda: User, secondary=ShoutViewer.__tablename__) + + @property + async def stat(self): + return { + "views": await ShoutViewStorage.get_view(self.slug), + "comments": await CommentStat.get_stat(self.slug), + "ratings": await ShoutRatingStorage.get_total_rating(self.slug) + } diff --git a/resolvers/zine.py b/resolvers/zine.py index cc66c336..92ee6830 100644 --- a/resolvers/zine.py +++ b/resolvers/zine.py @@ -88,7 +88,6 @@ class ShoutsCache: for row in session.execute(stmt): shout = row.Shout shout.ratings = await ShoutRatingStorage.get_ratings(shout.slug) - shout.views = await ShoutViewStorage.get_view(shout.slug) shouts.append(shout) async with ShoutsCache.lock: ShoutsCache.recent_shouts = shouts @@ -108,7 +107,6 @@ class ShoutsCache: for row in session.execute(stmt): shout = row.Shout shout.ratings = await ShoutRatingStorage.get_ratings(shout.slug) - shout.views = await ShoutViewStorage.get_view(shout.slug) shouts.append(shout) async with ShoutsCache.lock: ShoutsCache.top_overall = shouts @@ -128,7 +126,6 @@ class ShoutsCache: for row in session.execute(stmt): shout = row.Shout shout.ratings = await ShoutRatingStorage.get_ratings(shout.slug) - shout.views = await ShoutViewStorage.get_view(shout.slug) shouts.append(shout) async with ShoutsCache.lock: ShoutsCache.top_month = shouts @@ -336,7 +333,6 @@ async def get_shout_by_slug(_, info, slug): return {} #TODO return error field shout.ratings = await ShoutRatingStorage.get_ratings(slug) - shout.views = await ShoutViewStorage.get_view(slug) return shout @query.field("getShoutComments") diff --git a/schema.graphql b/schema.graphql index e41e72b9..677984d9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -307,8 +307,6 @@ type Shout { community: Int cover: String layout: String - rating: Int - views: Int # replyTo: Shout versionOf: Shout tags: [String] # actual values @@ -322,6 +320,14 @@ type Shout { deletedBy: Int publishedBy: Int # if there is no published field - it is not published publishedAt: DateTime + + stat: ShoutStat +} + +type ShoutStat { + views: Int! + comments: Int! + ratings: Int! } type Community {