From 9d94464614cb2f021be276d6a644da1b3387bc44 Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Sat, 5 Aug 2023 00:21:54 +0200 Subject: [PATCH] Revert "Revert "store views on the shouts table, remove the viewed table"" --- orm/__init__.py | 3 --- orm/shout.py | 9 ++++++-- orm/viewed.py | 24 --------------------- resolvers/zine/load.py | 45 ++++----------------------------------- services/stat/viewed.py | 47 ++++++++++++++++------------------------- 5 files changed, 29 insertions(+), 99 deletions(-) delete mode 100644 orm/viewed.py diff --git a/orm/__init__.py b/orm/__init__.py index b83e8ad8..bd2c9fb7 100644 --- a/orm/__init__.py +++ b/orm/__init__.py @@ -6,7 +6,6 @@ from orm.reaction import Reaction from orm.shout import Shout from orm.topic import Topic, TopicFollower from orm.user import User, UserRating -from orm.viewed import ViewedEntry # NOTE: keep orm module isolated @@ -22,7 +21,6 @@ __all__ = [ "Notification", "Reaction", "UserRating", - "ViewedEntry" ] @@ -35,5 +33,4 @@ def init_tables(): Role.init_table() UserRating.init_table() Shout.init_table() - ViewedEntry.init_table() print("[orm] tables initialized") diff --git a/orm/shout.py b/orm/shout.py index 5f3e2f4e..dfe9d749 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -1,7 +1,7 @@ from datetime import datetime -from sqlalchemy import Boolean, Column, DateTime, ForeignKey, String, JSON -from sqlalchemy.orm import relationship +from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String, JSON +from sqlalchemy.orm import column_property, relationship from base.orm import Base, local_session from orm.reaction import Reaction @@ -61,6 +61,11 @@ class Shout(Base): authors = relationship(lambda: User, secondary=ShoutAuthor.__tablename__) topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) + # views from the old Discours website + viewsOld = Column(Integer, default=0) + # views from Ackee tracker on the new Discours website + viewsAckee = Column(Integer, default=0) + views = column_property(viewsOld + viewsAckee) reactions = relationship(lambda: Reaction) # TODO: these field should be used or modified diff --git a/orm/viewed.py b/orm/viewed.py deleted file mode 100644 index 3f2441d5..00000000 --- a/orm/viewed.py +++ /dev/null @@ -1,24 +0,0 @@ -from datetime import datetime -from sqlalchemy import Column, DateTime, ForeignKey, Integer -from base.orm import Base, local_session - - -class ViewedEntry(Base): - __tablename__ = "viewed" - - viewer = Column(ForeignKey("user.id"), index=True, default=1) - shout = Column(ForeignKey("shout.id"), index=True, default=1) - amount = Column(Integer, default=1) - createdAt = Column( - DateTime, nullable=False, default=datetime.now, comment="Created at" - ) - - @staticmethod - def init_table(): - with local_session() as session: - entry = { - "amount": 0 - } - viewed = ViewedEntry.create(**entry) - session.add(viewed) - session.commit() diff --git a/resolvers/zine/load.py b/resolvers/zine/load.py index 46e7f028..7b36c5b6 100644 --- a/resolvers/zine/load.py +++ b/resolvers/zine/load.py @@ -8,7 +8,7 @@ from auth.credentials import AuthCredentials from base.exceptions import ObjectNotExist, OperationNotAllowed from base.orm import local_session from base.resolvers import query -from orm import ViewedEntry, TopicFollower +from orm import TopicFollower from orm.reaction import Reaction, ReactionKind from orm.shout import Shout, ShoutAuthor, ShoutTopic from orm.user import AuthorFollower @@ -101,24 +101,8 @@ async def load_shout(_, info, slug=None, shout_id=None): try: [shout, reacted_stat, commented_stat, rating_stat, last_comment] = session.execute(q).first() - viewed_stat_query = select().select_from( - Shout - ).where( - Shout.id == shout.id - ).join( - ViewedEntry - ).group_by( - Shout.id - ).add_columns( - func.sum(ViewedEntry.amount).label('viewed_stat') - ) - - # Debug tip: - # print(viewed_stat_query.compile(compile_kwargs={"literal_binds": True})) - viewed_stat = session.execute(viewed_stat_query).scalar() - shout.stat = { - "viewed": viewed_stat, + "viewed": shout.views, "reacted": reacted_stat, "commented": commented_stat, "rating": rating_stat @@ -133,23 +117,6 @@ async def load_shout(_, info, slug=None, shout_id=None): raise ObjectNotExist("Slug was not found: %s" % slug) -def add_viewed_stat(session, shouts_map): - viewed_stat_query = select( - Shout.id - ).where( - Shout.id.in_(shouts_map.keys()) - ).join( - ViewedEntry - ).group_by( - Shout.id - ).add_columns( - func.sum(ViewedEntry.amount).label('viewed_stat') - ) - - for [shout_id, viewed_stat] in session.execute(viewed_stat_query).unique(): - shouts_map[shout_id].stat['viewed'] = viewed_stat - - @query.field("loadShouts") async def load_shouts_by(_, info, options): """ @@ -199,15 +166,13 @@ async def load_shouts_by(_, info, options): for [shout, reacted_stat, commented_stat, rating_stat, last_comment] in session.execute(q).unique(): shouts.append(shout) shout.stat = { - "viewed": 0, + "viewed": shout.views, "reacted": reacted_stat, "commented": commented_stat, "rating": rating_stat } shouts_map[shout.id] = shout - add_viewed_stat(session, shouts_map) - return shouts @@ -277,13 +242,11 @@ async def get_my_feed(_, info, options): for [shout, reacted_stat, commented_stat, rating_stat, last_comment] in session.execute(q).unique(): shouts.append(shout) shout.stat = { - "viewed": 0, + "viewed": shout.views, "reacted": reacted_stat, "commented": commented_stat, "rating": rating_stat } shouts_map[shout.id] = shout - add_viewed_stat(session, shouts_map) - return shouts diff --git a/services/stat/viewed.py b/services/stat/viewed.py index 779a6e93..905ade43 100644 --- a/services/stat/viewed.py +++ b/services/stat/viewed.py @@ -11,7 +11,6 @@ from sqlalchemy import func from base.orm import local_session from orm import User, Topic from orm.shout import ShoutTopic, Shout -from orm.viewed import ViewedEntry load_facts = gql(""" query getDomains { @@ -128,10 +127,7 @@ class ViewedStorage: with local_session() as session: try: shout = session.query(Shout).where(Shout.slug == shout_slug).one() - shout_views = session.query(func.sum(ViewedEntry.amount)).where( - ViewedEntry.shout == shout.id - ).all()[0][0] - self.by_shouts[shout_slug] = shout_views + self.by_shouts[shout_slug] = shout.views self.update_topics(session, shout_slug) except Exception as e: raise e @@ -160,37 +156,30 @@ class ViewedStorage: self.by_topics[topic.slug][shout_slug] = self.by_shouts[shout_slug] @staticmethod - async def increment(shout_slug, amount=1, viewer='anonymous'): + async def increment(shout_slug, amount=1, viewer='ackee'): """ the only way to change views counter """ self = ViewedStorage async with self.lock: + # TODO optimize, currenty we execute 1 DB transaction per shout with local_session() as session: - # TODO: user slug -> id - viewed = session.query( - ViewedEntry - ).join( - Shout, Shout.id == ViewedEntry.shout - ).join( - User, User.id == ViewedEntry.viewer - ).filter( - User.slug == viewer, - Shout.slug == shout_slug - ).first() - - if viewed: - viewed.amount = amount - print("amount: %d" % amount) + shout = session.query(Shout).where(Shout.slug == shout_slug).one() + if viewer == 'old-discours': + # this is needed for old db migration + if shout.viewsOld == amount: + print(f"viewsOld amount: {amount}") + else: + print(f"viewsOld amount changed: {shout.viewsOld} --> {amount}") + shout.viewsOld = amount else: - shout = session.query(Shout).where(Shout.slug == shout_slug).one() - viewer = session.query(User).where(User.slug == viewer).one() - new_viewed = ViewedEntry.create(**{ - "viewer": viewer.id, - "shout": shout.id, - "amount": amount - }) - session.add(new_viewed) + if shout.viewsAckee == amount: + print(f"viewsAckee amount: {amount}") + else: + print(f"viewsAckee amount changed: {shout.viewsAckee} --> {amount}") + shout.viewsAckee = amount session.commit() + + # this part is currently unused self.by_shouts[shout_slug] = self.by_shouts.get(shout_slug, 0) + amount self.update_topics(session, shout_slug)