From fdafa207eda41f152ac4db078c2800113a575cd1 Mon Sep 17 00:00:00 2001 From: Viet Than Date: Thu, 7 Sep 2023 22:32:36 -0400 Subject: [PATCH] passed the test --- files/classes/views.py | 18 +++++-- files/routes/users.py | 6 ++- ...d682a_change_to_datetimez_table_viewers.py | 53 +++++++++++++++++++ 3 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 migrations/versions/2023_09_08_02_14_46_bcfaec0d682a_change_to_datetimez_table_viewers.py diff --git a/files/classes/views.py b/files/classes/views.py index 18ad428d7..46f9c2e96 100644 --- a/files/classes/views.py +++ b/files/classes/views.py @@ -2,6 +2,7 @@ import time from sqlalchemy import * from sqlalchemy.orm import relationship +from sqlalchemy.sql.functions import now from files.classes.base import Base from files.helpers.lazy import lazy @@ -13,17 +14,24 @@ class ViewerRelationship(Base): user_id = Column(Integer, ForeignKey('users.id'), primary_key=True) viewer_id = Column(Integer, ForeignKey('users.id'), primary_key=True) - last_view_utc = Column(Integer, nullable=False) + last_view_datetimez = Column(DateTime(timezone=True), nullable=False, server_default=now()) Index('fki_view_viewer_fkey', viewer_id) viewer = relationship("User", primaryjoin="ViewerRelationship.viewer_id == User.id", viewonly=True) - def __init__(self, **kwargs): - if 'last_view_utc' not in kwargs: - kwargs['last_view_utc'] = int(time.time()) + # def __init__(self, **kwargs): + # if 'last_view_utc' not in kwargs: + # kwargs['last_view_utc'] = int(time.time()) - super().__init__(**kwargs) + # super().__init__(**kwargs) + + @property + def last_view_utc(self): + """ + the last view timestamp in UTC seconds. Milliseconds are truncated/rounded down. + """ + return int(self.last_view_datetimez.timestamp()) @property @lazy diff --git a/files/routes/users.py b/files/routes/users.py index 8c42348e2..a016e2c87 100644 --- a/files/routes/users.py +++ b/files/routes/users.py @@ -2,6 +2,7 @@ import io import math import time from collections import Counter +from datetime import datetime from urllib.parse import urlparse import gevent @@ -633,7 +634,7 @@ def following(v, username): @auth_required def visitors(v): if v.admin_level < 2 and not v.patron: return render_template("errors/patron.html", v=v) - viewers=sorted(v.viewers, key = lambda x: x.last_view_utc, reverse=True) + viewers=sorted(v.viewers, key = lambda x: x.last_view_datetimez, reverse=True) return render_template("viewers.html", v=v, viewers=viewers) @@ -651,7 +652,8 @@ def u_username(username, v=None): if v and v.id != u.id and (u.patron or u.admin_level > 1): view = g.db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none() - if view: view.last_view_utc = int(time.time()) + # if view: view.last_view_datetimez = int(time.time()) + if view: view.last_view_datetimez = datetime.utcnow() else: view = ViewerRelationship(viewer_id=v.id, user_id=u.id) g.db.add(view) diff --git a/migrations/versions/2023_09_08_02_14_46_bcfaec0d682a_change_to_datetimez_table_viewers.py b/migrations/versions/2023_09_08_02_14_46_bcfaec0d682a_change_to_datetimez_table_viewers.py new file mode 100644 index 000000000..04f1d3e50 --- /dev/null +++ b/migrations/versions/2023_09_08_02_14_46_bcfaec0d682a_change_to_datetimez_table_viewers.py @@ -0,0 +1,53 @@ +"""Change to datetimez table viewers + +Revision ID: bcfaec0d682a +Revises: a2fce4808e1d +Create Date: 2023-09-08 02:14:46.989072+00:00 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.sql.functions import now + + +# revision identifiers, used by Alembic. +revision = 'bcfaec0d682a' +down_revision = 'a2fce4808e1d' +branch_labels = None +depends_on = None + +table_name = 'viewers' +from_column = 'last_view_utc' +to_column = 'last_view_datetimez' + + +def upgrade(): + op.add_column(table_name, sa.Column(to_column, sa.DateTime(timezone=True), nullable=True, server_default=now())) + op.execute(f""" + UPDATE {table_name} + SET {to_column} = + CASE + WHEN {from_column} > 0 THEN + (timestamp 'epoch' + {from_column} * interval '1 second') at time zone 'utc' + ELSE NULL + END + """) + op.alter_column(table_name, to_column, nullable=False) + op.drop_column(table_name, from_column) + + +def downgrade(): + """ + Downgrade will truncate the milliseconds. + """ + op.add_column(table_name, sa.Column('created_utc', sa.Integer(), server_default=sa.text('0'), nullable=True)) + op.execute(f""" + UPDATE {table_name} + SET created_utc = + COALESCE( + EXTRACT(EPOCH FROM {to_column})::integer, + 0 + ) + """) + op.alter_column(table_name, from_column, nullable=False) + op.drop_column(table_name, to_column) \ No newline at end of file