add topic stat

This commit is contained in:
knst-kotov 2021-12-13 19:51:01 +03:00
parent 5a47951b66
commit ab9990a616
4 changed files with 60 additions and 2 deletions

View File

@ -15,7 +15,7 @@ from redis import redis
from resolvers.base import resolvers from resolvers.base import resolvers
from resolvers.zine import GitTask, ShoutsCache from resolvers.zine import GitTask, ShoutsCache
from orm.shout import ShoutViewStorage from orm.shout import ShoutViewStorage, TopicStat
import asyncio import asyncio
@ -32,6 +32,7 @@ async def start_up():
git_task = asyncio.create_task(GitTask.git_task_worker()) git_task = asyncio.create_task(GitTask.git_task_worker())
shouts_cache_task = asyncio.create_task(ShoutsCache.worker()) shouts_cache_task = asyncio.create_task(ShoutsCache.worker())
view_storage_task = asyncio.create_task(ShoutViewStorage.worker()) view_storage_task = asyncio.create_task(ShoutViewStorage.worker())
topic_stat_task = asyncio.create_task(TopicStat.worker())
async def shutdown(): async def shutdown():
await redis.disconnect() await redis.disconnect()

View File

@ -140,6 +140,51 @@ class ShoutViewStorage:
print("ShoutViewStorage worker: error = %s" % (err)) print("ShoutViewStorage worker: error = %s" % (err))
await asyncio.sleep(ShoutViewStorage.period) await asyncio.sleep(ShoutViewStorage.period)
class TopicStat:
shouts_by_topic = {}
lock = asyncio.Lock()
period = 30*60 #sec
@staticmethod
async def load_stat(session):
self = TopicStat
shout_topics = session.query(ShoutTopic)
for shout_topic in shout_topics:
topic = shout_topic.topic
shout = shout_topic.shout
if topic in self.shouts_by_topic:
self.shouts_by_topic[topic].append(shout)
else:
self.shouts_by_topic[topic] = [shout]
@staticmethod
async def get_stat(topic):
self = TopicStat
async with self.lock:
shouts = self.shouts_by_topic.get(topic, [])
stat = { "shouts" : len(shouts) }
views = 0
for shout in shouts:
views += await ShoutViewStorage.get_view(shout)
stat["views"] = views
return stat
@staticmethod
async def worker():
self = TopicStat
print("TopicStat worker start")
while True:
try:
print("TopicStat worker: load stat")
with local_session() as session:
async with self.lock:
await self.load_stat(session)
except Exception as err:
print("TopicStat worker: error = %s" % (err))
await asyncio.sleep(self.period)
class Shout(Base): class Shout(Base):
__tablename__ = 'shout' __tablename__ = 'shout'

View File

@ -1,4 +1,5 @@
from orm import Topic, TopicSubscription, TopicStorage, Shout, User from orm import Topic, TopicSubscription, TopicStorage, Shout, User
from orm.shout import TopicStat
from orm.base import local_session from orm.base import local_session
from resolvers.base import mutation, query, subscription from resolvers.base import mutation, query, subscription
from resolvers.zine import ShoutSubscriptions from resolvers.zine import ShoutSubscriptions
@ -8,7 +9,12 @@ import asyncio
@query.field("topicsBySlugs") @query.field("topicsBySlugs")
async def topics_by_slugs(_, info, slugs = None): async def topics_by_slugs(_, info, slugs = None):
with local_session() as session: with local_session() as session:
return await TopicStorage.get_topics(slugs) topics = await TopicStorage.get_topics(slugs)
all_fields = [node.name.value for node in info.field_nodes[0].selection_set.selections]
if "topicStat" in all_fields:
for topic in topics:
topic.topicStat = await TopicStat.get_stat(topic.slug)
return topics
@query.field("topicsByCommunity") @query.field("topicsByCommunity")
async def topics_by_community(_, info, community): async def topics_by_community(_, info, community):

View File

@ -331,6 +331,11 @@ type Community {
pic: String! pic: String!
} }
type TopicStat {
shouts: Int
views: Int
}
type Topic { type Topic {
slug: String! # ID slug: String! # ID
title: String title: String
@ -339,6 +344,7 @@ type Topic {
parents: [String] # NOTE: topic can have parent topics parents: [String] # NOTE: topic can have parent topics
children: [String] # and children children: [String] # and children
community: String! community: String!
topicStat: TopicStat
} }
# TODO: resolvers to add/remove topics from publication # TODO: resolvers to add/remove topics from publication