ShoutAuthor storage removed, minor fixes

This commit is contained in:
Igor Lobanov 2022-11-28 21:34:42 +01:00
parent 49ac3e97e5
commit e5b3bdc63c
4 changed files with 41 additions and 67 deletions

View File

@ -1,7 +1,6 @@
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
import sqlalchemy as sa
from sqlalchemy.orm import joinedload, aliased from sqlalchemy.orm import joinedload, aliased
from sqlalchemy.sql.expression import desc, asc, select, case from sqlalchemy.sql.expression import desc, asc, select, case, func
from base.orm import local_session from base.orm import local_session
from base.resolvers import query from base.resolvers import query
from orm import ViewedEntry from orm import ViewedEntry
@ -10,21 +9,21 @@ from orm.reaction import Reaction, ReactionKind
def add_stat_columns(q): def add_stat_columns(q):
q = q.outerjoin(ViewedEntry).add_columns(sa.func.sum(ViewedEntry.amount).label('viewed_stat')) q = q.outerjoin(ViewedEntry).add_columns(func.sum(ViewedEntry.amount).label('viewed_stat'))
aliased_reaction = aliased(Reaction) aliased_reaction = aliased(Reaction)
q = q.outerjoin(aliased_reaction).add_columns( q = q.outerjoin(aliased_reaction).add_columns(
sa.func.sum( func.sum(
aliased_reaction.id aliased_reaction.id
).label('reacted_stat'), ).label('reacted_stat'),
sa.func.sum( func.sum(
case( case(
(aliased_reaction.body.is_not(None), 1), (aliased_reaction.body.is_not(None), 1),
else_=0 else_=0
) )
).label('commented_stat'), ).label('commented_stat'),
sa.func.sum(case( func.sum(case(
(aliased_reaction.kind == ReactionKind.AGREE, 1), (aliased_reaction.kind == ReactionKind.AGREE, 1),
(aliased_reaction.kind == ReactionKind.DISAGREE, -1), (aliased_reaction.kind == ReactionKind.DISAGREE, -1),
(aliased_reaction.kind == ReactionKind.PROOF, 1), (aliased_reaction.kind == ReactionKind.PROOF, 1),
@ -135,7 +134,7 @@ async def load_shouts_by(_, info, options):
order_by = options.get("order_by", Shout.createdAt) order_by = options.get("order_by", Shout.createdAt)
if order_by == 'reacted': if order_by == 'reacted':
aliased_reaction = aliased(Reaction) aliased_reaction = aliased(Reaction)
q.outerjoin(aliased_reaction).add_columns(sa.func.max(aliased_reaction.createdAt).label('reacted')) q.outerjoin(aliased_reaction).add_columns(func.max(aliased_reaction.createdAt).label('reacted'))
order_by_desc = options.get('order_by_desc', True) order_by_desc = options.get('order_by_desc', True)

View File

@ -1,7 +1,6 @@
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from sqlalchemy import and_, asc, desc, select, text, func from sqlalchemy import and_, asc, desc, select, text, func, case
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from auth.authenticate import login_required from auth.authenticate import login_required
from base.orm import local_session from base.orm import local_session
from base.resolvers import mutation, query from base.resolvers import mutation, query
@ -10,6 +9,34 @@ from orm.shout import Shout, ShoutReactionsFollower
from orm.user import User from orm.user import User
def add_reaction_stat_columns(q):
aliased_reaction = aliased(Reaction)
q = q.outerjoin(aliased_reaction).add_columns(
func.sum(
aliased_reaction.id
).label('reacted_stat'),
func.sum(
case(
(aliased_reaction.body.is_not(None), 1),
else_=0
)
).label('commented_stat'),
func.sum(case(
(aliased_reaction.kind == ReactionKind.AGREE, 1),
(aliased_reaction.kind == ReactionKind.DISAGREE, -1),
(aliased_reaction.kind == ReactionKind.PROOF, 1),
(aliased_reaction.kind == ReactionKind.DISPROOF, -1),
(aliased_reaction.kind == ReactionKind.ACCEPT, 1),
(aliased_reaction.kind == ReactionKind.REJECT, -1),
(aliased_reaction.kind == ReactionKind.LIKE, 1),
(aliased_reaction.kind == ReactionKind.DISLIKE, -1),
else_=0)
).label('rating_stat'))
return q
def reactions_follow(user: User, slug: str, auto=False): def reactions_follow(user: User, slug: str, auto=False):
with local_session() as session: with local_session() as session:
following = ( following = (

View File

@ -1,6 +1,4 @@
import sqlalchemy as sa from sqlalchemy import and_, select, distinct, func
from sqlalchemy import and_, select, distinct
from auth.authenticate import login_required from auth.authenticate import login_required
from base.orm import local_session from base.orm import local_session
from base.resolvers import mutation, query from base.resolvers import mutation, query
@ -11,15 +9,15 @@ from orm import Shout
def add_topic_stat_columns(q): def add_topic_stat_columns(q):
q = q.outerjoin(ShoutTopic, Topic.slug == ShoutTopic.topic).add_columns( q = q.outerjoin(ShoutTopic, Topic.slug == ShoutTopic.topic).add_columns(
sa.func.count(distinct(ShoutTopic.shout)).label('shouts_stat') func.count(distinct(ShoutTopic.shout)).label('shouts_stat')
).outerjoin(ShoutAuthor, ShoutTopic.shout == ShoutAuthor.shout).add_columns( ).outerjoin(ShoutAuthor, ShoutTopic.shout == ShoutAuthor.shout).add_columns(
sa.func.count(distinct(ShoutAuthor.user)).label('authors_stat') func.count(distinct(ShoutAuthor.user)).label('authors_stat')
).outerjoin(TopicFollower, ).outerjoin(TopicFollower,
and_( and_(
TopicFollower.topic == Topic.slug, TopicFollower.topic == Topic.slug,
TopicFollower.follower == ShoutAuthor.user TopicFollower.follower == ShoutAuthor.user
)).add_columns( )).add_columns(
sa.func.count(distinct(TopicFollower.follower)).label('followers_stat') func.count(distinct(TopicFollower.follower)).label('followers_stat')
) )
q = q.group_by(Topic.id) q = q.group_by(Topic.id)
@ -56,7 +54,6 @@ def followed_by_user(user_slug):
return get_topics_from_query(q) return get_topics_from_query(q)
@query.field("topicsAll") @query.field("topicsAll")
async def topics_all(_, _info): async def topics_all(_, _info):
q = select(Topic) q = select(Topic)
@ -146,7 +143,7 @@ async def topic_unfollow(user, slug):
async def topics_random(_, info, amount=12): async def topics_random(_, info, amount=12):
q = select(Topic) q = select(Topic)
q = add_topic_stat_columns(q) q = add_topic_stat_columns(q)
q = q.join(Shout, ShoutTopic.shout == Shout.slug).group_by(Topic.id).having(sa.func.count(Shout.id) > 2) q = q.join(Shout, ShoutTopic.shout == Shout.slug).group_by(Topic.id).having(func.count(Shout.id) > 2)
q = q.order_by(sa.func.random()).limit(amount) q = q.order_by(func.random()).limit(amount)
return get_topics_from_query(q) return get_topics_from_query(q)

View File

@ -1,49 +0,0 @@
import asyncio
import time
from base.orm import local_session
from orm.shout import ShoutAuthor
class ShoutAuthorStorage:
authors_by_shout = {}
lock = asyncio.Lock()
# period = 30 * 60 # sec
@staticmethod
async def load_captions(session):
self = ShoutAuthorStorage
sas = session.query(ShoutAuthor).all()
for sa in sas:
self.authors_by_shout[sa.shout] = self.authors_by_shout.get(sa.shout, {})
self.authors_by_shout[sa.shout][sa.user] = sa.caption
print("[zine.authors] ⎧ %d shouts indexed by authors" % len(self.authors_by_shout))
@staticmethod
async def get_author_caption(shout, author):
self = ShoutAuthorStorage
async with self.lock:
return self.authors_by_shout.get(shout, {}).get(author)
@staticmethod
async def set_author_caption(shout, author, caption):
self = ShoutAuthorStorage
async with self.lock:
self.authors_by_shout[shout] = self.authors_by_shout.get(shout, {})
self.authors_by_shout[shout][author] = caption
return {
"error": None,
}
@staticmethod
async def worker():
self = ShoutAuthorStorage
async with self.lock:
# while True:
try:
with local_session() as session:
ts = time.time()
await self.load_captions(session)
print("[zine.authors] ⎩ load_captions took %fs " % (time.time() - ts))
except Exception as err:
print("[zine.authors] ⎩ error indexing by author: %s" % (err))
# await asyncio.sleep(self.period)