From cfc1beeec015218e9018dfbf0151226678ebad9f Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Fri, 25 Nov 2022 19:31:53 +0100 Subject: [PATCH] WIP --- CHECKS | 2 +- main.py | 5 +- migration/tables/comments.py | 2 - migration/tables/content_items.py | 1 - orm/__init__.py | 2 +- resolvers/__init__.py | 3 +- resolvers/zine/load.py | 117 ++++++++++++++++-------------- resolvers/zine/reactions.py | 1 - 8 files changed, 66 insertions(+), 67 deletions(-) diff --git a/CHECKS b/CHECKS index 5affecfc..e2d41a77 100644 --- a/CHECKS +++ b/CHECKS @@ -1,5 +1,5 @@ WAIT=30 TIMEOUT=10 -ATTEMPTS=60 # 60 * 30 = 30 min +ATTEMPTS=20 # 20 * 30 = 10 min / Playground diff --git a/main.py b/main.py index 4384016d..7b8fcee9 100644 --- a/main.py +++ b/main.py @@ -35,13 +35,10 @@ async def start_up(): await storages_init() views_stat_task = asyncio.create_task(ViewedStorage().worker()) print(views_stat_task) - reacted_storage_task = asyncio.create_task(ReactedStorage.worker()) - print(reacted_storage_task) - topic_stat_task = asyncio.create_task(TopicStat.worker()) - print(topic_stat_task) git_task = asyncio.create_task(GitTask.git_task_worker()) print(git_task) + async def dev_start_up(): if exists(DEV_SERVER_STATUS_FILE_NAME): return diff --git a/migration/tables/comments.py b/migration/tables/comments.py index 944cad1c..9fb099f7 100644 --- a/migration/tables/comments.py +++ b/migration/tables/comments.py @@ -76,7 +76,6 @@ async def migrate(entry, storage): # creating reaction from old comment reaction = Reaction.create(**reaction_dict) session.add(reaction) - await ReactedStorage.react(reaction) # creating shout's reactions following for reaction author following1 = session.query( @@ -147,7 +146,6 @@ async def migrate(entry, storage): ) session.add(following2) session.add(rr) - await ReactedStorage.react(rr) except Exception as e: print("[migration] comment rating error: %r" % re_reaction_dict) diff --git a/migration/tables/content_items.py b/migration/tables/content_items.py index 926e28d3..9f490eb8 100644 --- a/migration/tables/content_items.py +++ b/migration/tables/content_items.py @@ -335,7 +335,6 @@ async def migrate(entry, storage): else: rea = Reaction.create(**reaction_dict) session.add(rea) - await ReactedStorage.react(rea) # shout_dict['ratings'].append(reaction_dict) session.commit() diff --git a/orm/__init__.py b/orm/__init__.py index c8251256..b83e8ad8 100644 --- a/orm/__init__.py +++ b/orm/__init__.py @@ -21,7 +21,7 @@ __all__ = [ "TopicFollower", "Notification", "Reaction", - "UserRating" + "UserRating", "ViewedEntry" ] diff --git a/resolvers/__init__.py b/resolvers/__init__.py index fccca3a0..8e504ab7 100644 --- a/resolvers/__init__.py +++ b/resolvers/__init__.py @@ -15,7 +15,8 @@ from resolvers.create.editor import create_shout, delete_shout, update_shout from resolvers.zine.profile import ( load_authors_by, rate_user, - update_profile + update_profile, + get_authors_all ) from resolvers.zine.reactions import ( diff --git a/resolvers/zine/load.py b/resolvers/zine/load.py index d25167ed..531ece51 100644 --- a/resolvers/zine/load.py +++ b/resolvers/zine/load.py @@ -1,6 +1,6 @@ from datetime import datetime, timedelta, timezone import sqlalchemy as sa -from sqlalchemy.orm import joinedload +from sqlalchemy.orm import joinedload, aliased, make_transient from sqlalchemy.sql.expression import desc, asc, select, case from base.orm import local_session from base.resolvers import query @@ -9,8 +9,25 @@ from orm.shout import Shout, ShoutAuthor from orm.reaction import Reaction, ReactionKind -def add_rating_column(q): - return q.join(Reaction).add_columns(sa.func.sum(case( +def add_viewed_stat_column(q): + return q.outerjoin(ViewedEntry).add_columns(sa.func.sum(ViewedEntry.amount).label('viewed_stat')) + + +def add_reacted_stat_column(q): + aliased_reaction = aliased(Reaction) + return q.outerjoin(aliased_reaction).add_columns(sa.func.count(aliased_reaction.id).label('reacted_stat')) + + +def add_commented_stat_column(q): + aliased_reaction = aliased(Reaction) + return q.outerjoin( + aliased_reaction, + aliased_reaction.shout == Shout.slug and aliased_reaction.body.is_not(None) + ).add_columns(sa.func.count(aliased_reaction.id).label('commented_stat')) + + +def add_rating_stat_column(q): + return q.outerjoin(Reaction).add_columns(sa.func.sum(case( (Reaction.kind == ReactionKind.AGREE, 1), (Reaction.kind == ReactionKind.DISAGREE, -1), (Reaction.kind == ReactionKind.PROOF, 1), @@ -20,7 +37,7 @@ def add_rating_column(q): (Reaction.kind == ReactionKind.LIKE, 1), (Reaction.kind == ReactionKind.DISLIKE, -1), else_=0 - )).label('rating')) + )).label('rating_stat')) def apply_filters(q, filters, user=None): @@ -45,6 +62,14 @@ def apply_filters(q, filters, user=None): return q +def add_stat_columns(q): + q = add_viewed_stat_column(q) + q = add_reacted_stat_column(q) + q = add_commented_stat_column(q) + q = add_rating_stat_column(q) + return q + + @query.field("loadShout") async def load_shout(_, info, slug): with local_session() as session: @@ -53,26 +78,30 @@ async def load_shout(_, info, slug): joinedload(Shout.authors), joinedload(Shout.topics), ) - q = add_rating_column(q) + q = add_stat_columns(q) q = q.filter( Shout.slug == slug ).filter( Shout.deletedAt.is_(None) ).group_by(Shout.id) - [shout, rating] = session.execute(q).unique().one() + [shout, viewed_stat, reacted_stat, commented_stat, rating_stat] = session.execute(q).unique().one() - shout.stat = await ReactedStorage.get_shout_stat(shout.slug, rating) + shout.stat = { + "viewed": viewed_stat, + "reacted": reacted_stat, + "commented": commented_stat, + "rating": rating_stat + } + + for author_caption in session.query(ShoutAuthor).where(ShoutAuthor.shout == slug): + for author in shout.authors: + if author.slug == author_caption.user: + author.caption = author_caption.caption return shout -def map_result_item(result_item): - shout = result_item[0] - shout.rating = result_item[1] - return shout - - @query.field("loadShouts") async def load_shouts_by(_, info, options): """ @@ -88,7 +117,7 @@ async def load_shouts_by(_, info, options): } offset: 0 limit: 50 - order_by: 'createdAt' + order_by: 'createdAt' | 'commented' | 'reacted' | 'rating' order_by_desc: true } @@ -101,60 +130,36 @@ async def load_shouts_by(_, info, options): ).where( Shout.deletedAt.is_(None) ) + + q = add_stat_columns(q) + user = info.context["request"].user q = apply_filters(q, options.get("filters"), user) - q = add_rating_column(q) - o = options.get("order_by") - if o: - if o == 'comments': - q = q.add_columns(sa.func.count(Reaction.id).label(o)) - q = q.join(Reaction, Shout.slug == Reaction.shout) - q = q.filter(Reaction.body.is_not(None)) - elif o == 'reacted': - q = q.join( - Reaction - ).add_columns( - sa.func.max(Reaction.createdAt).label(o) - ) - elif o == 'views': - q = q.join(ViewedEntry) - q = q.add_columns(sa.func.sum(ViewedEntry.amount).label(o)) - order_by = o - else: - order_by = Shout.createdAt + order_by = options.get("order_by", Shout.createdAt) + if order_by == 'reacted': + aliased_reaction = aliased(Reaction) + q.outerjoin(aliased_reaction).add_columns(sa.func.max(aliased_reaction.createdAt).label('reacted')) - order_by_desc = True if options.get('order_by_desc') is None else options.get('order_by_desc') - - with_author_captions = False if options.get('with_author_captions') is None else options.get('with_author_captions') + order_by_desc = options.get('order_by_desc', True) query_order_by = desc(order_by) if order_by_desc else asc(order_by) offset = options.get("offset", 0) limit = options.get("limit", 10) + q = q.group_by(Shout.id).order_by(query_order_by).limit(limit).offset(offset) with local_session() as session: - results = session.execute(q).unique() - for [shout, rating] in results: - shout.stat = await ReactedStorage.get_shout_stat(shout.slug, rating) + shouts = [] - author_captions = {} + for [shout, viewed_stat, reacted_stat, commented_stat, rating_stat] in session.execute(q).unique(): + shouts.append(shout) - if with_author_captions: - author_captions_result = session.query(ShoutAuthor).where( - ShoutAuthor.shout.in_(map(lambda result_item: result_item[0].slug, results))).all() - - for author_captions_result_item in author_captions_result: - if author_captions.get(author_captions_result_item.shout) is None: - author_captions[author_captions_result_item.shout] = {} - - author_captions[ - author_captions_result_item.shout - ][ - author_captions_result_item.user - ] = author_captions_result_item.caption - - for author in shout.authors: - author.caption = author_captions[shout.slug][author.slug] + shout.stat = { + "viewed": viewed_stat, + "reacted": reacted_stat, + "commented": commented_stat, + "rating": rating_stat + } return shouts diff --git a/resolvers/zine/reactions.py b/resolvers/zine/reactions.py index e3fcf416..5ac648aa 100644 --- a/resolvers/zine/reactions.py +++ b/resolvers/zine/reactions.py @@ -141,7 +141,6 @@ async def create_reaction(_, info, inp): elif check_to_publish(session, user, reaction): set_published(session, reaction.shout, reaction.createdBy) - ReactedStorage.react(reaction) try: reactions_follow(user, inp["shout"], True) except Exception as e: