schema-fix
All checks were successful
deploy / deploy (push) Successful in 1m18s

This commit is contained in:
Untone 2023-11-26 21:21:14 +03:00
parent 391958e60c
commit 2eaefaa62f
4 changed files with 79 additions and 69 deletions

View File

@ -16,15 +16,13 @@ async def start_up():
if MODE == "dev":
if exists(DEV_SERVER_PID_FILE_NAME):
await redis.connect()
return
else:
with open(DEV_SERVER_PID_FILE_NAME, "w", encoding="utf-8") as f:
f.write(str(os.getpid()))
else:
await redis.connect()
notification_service_task = asyncio.create_task(reactions_worker())
print(f"[main] {notification_service_task}")
print(f"[main.start_up] {notification_service_task}")
try:
import sentry_sdk

View File

@ -1,8 +1,9 @@
from enum import Enum as Enumeration
import time
from sqlalchemy import Boolean, Column, Enum, Integer
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy import Boolean, Column, Enum, Integer, ForeignKey, JSON as JSONType
from sqlalchemy.orm import relationship
# from sqlalchemy.dialects.postgresql import JSONB
from orm.author import Author
from services.db import Base
@ -21,12 +22,19 @@ class NotificationAction(Enumeration):
UNFOLLOW = 6
class NotificationSeen(Base):
__tablename__ = "notification_seen"
viewer = Column(ForeignKey("author.id"))
notification = Column(ForeignKey("notification.id"))
class Notification(Base):
__tablename__ = "notification"
created_at = Column(Integer, default=lambda: int(time.time()))
seen = Column(Boolean, nullable=False, default=False, index=True)
entity = Column(Enum(NotificationEntity), nullable=False)
action = Column(Enum(NotificationAction), nullable=False)
payload = Column(JSONB, nullable=True)
# occurrences = Column(Integer, default=1)
payload = Column(JSONType, nullable=True)
seen = relationship(lambda: Author, secondary="notification_seen")

View File

@ -17,11 +17,13 @@ redis = {extras = ["hiredis"], version = "^5.0.1"}
uvicorn = "^0.24.0.post1"
strawberry-graphql = {extras = ["asgi", "debug-server"], version = "^0.215.1" }
sentry-sdk = "^1.37.1"
strawberry-sqlalchemy-mapper = "^0.3.1"
[tool.poetry.dev-dependencies]
pytest = "^7.4.2"
black = { version = "^23.9.1", python = ">=3.12" }
mypy = { version = "^1.7", python = ">=3.12" }
setuptools = "^69.0.2"
[tool.black]
line-length = 120

View File

@ -1,27 +1,25 @@
from typing import List
from typing import List, Any
import strawberry
from sqlalchemy import and_
from sqlalchemy.orm import aliased
from orm.author import Author
from orm.notification import Notification as NotificationMessage, NotificationSeen
from services.auth import login_required
from services.db import local_session
from strawberry_sqlalchemy_mapper import StrawberrySQLAlchemyMapper
import strawberry
strawberry_sqlalchemy_mapper = StrawberrySQLAlchemyMapper()
@strawberry.type
class NotificationSeen:
notification: int # notification id
viewer: int # author id
@strawberry.type
@strawberry_sqlalchemy_mapper.type(NotificationMessage)
class Notification:
id: int
action: str # create update delete join follow etc.
entity: str # REACTION SHOUT
created_at: int
seen: list[NotificationSeen]
data: str # JSON data
occurrences: int
payload: str # JSON data
seen: List[int]
@strawberry.type
@ -35,14 +33,6 @@ class NotificationsResult:
unread: int
total: int
def notification_seen_by_viewer(viewer_id, notification_id, session):
seen = (
session.query(NotificationSeen)
.filter(NotificationSeen.viewer == viewer_id, NotificationSeen.notification == notification_id)
.first()
)
return seen is not None
@strawberry.type
class Query:
@ -50,25 +40,32 @@ class Query:
@login_required
async def load_notifications(self, info, limit: int = 50, offset: int = 0) -> NotificationsResult:
user_id = info.context["user_id"]
nr = NotificationsResult()
with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first()
NotificationSeenAlias = aliased(NotificationSeen)
query = (
session.query(Notification)
.outerjoin(
if author:
nnn = session.query(
NotificationMessage,
NotificationSeenAlias.viewer.label("seen")
).outerjoin(
NotificationSeen,
and_(NotificationSeen.viewer == author.id, NotificationSeen.notification == Notification.id),
)
.limit(limit)
.offset(offset)
)
nslist = query.all()
total = query.group_by(Notification.id).count()
unread = sum(1 for n in nslist if not n.seen_by_viewer)
return NotificationsResult(notifications=nslist, unread=unread, total=total)
and_(NotificationSeen.viewer == author.id, NotificationSeen.notification == NotificationMessage.id),
).limit(limit).offset(offset).all()
nr.notifications = []
for n in nnn:
ntf = Notification()
ntf.id = n.id
ntf.payload = n.payload
ntf.entity = n.entity
ntf.action = n.action
ntf.created_at = n.created_at
ntf.seen = n.seen
nr.notifications.append(ntf)
nr.unread = sum(1 for n in nr.notifications if author.id in n.seen)
nr.total = session.query(NotificationMessage).count()
return nr
@strawberry.type
@ -77,8 +74,8 @@ class Mutation:
@login_required
async def mark_notification_as_read(self, info, notification_id: int) -> NotificationSeenResult:
user_id = info.context["user_id"]
try:
with local_session() as session:
try:
author = session.query(Author).filter(Author.user == user_id).first()
ns = NotificationSeen({"notification": notification_id, "viewer": author.id})
session.add(ns)
@ -86,7 +83,9 @@ class Mutation:
except Exception as e:
session.rollback()
print(f"[mark_notification_as_read] error: {str(e)}")
return NotificationSeenResult(error="cant mark as read")
nsr = NotificationSeenResult()
nsr.error = "cant mark as read"
return nsr
return NotificationSeenResult()
@strawberry.mutation
@ -97,11 +96,14 @@ class Mutation:
with local_session() as session:
try:
author = session.query(Author).filter(Author.user == user_id).first()
_nslist = session.quuery(NotificationSeen).filter(NotificationSeen.viewer == author.id).all()
if author:
_nslist = session.query(NotificationSeen).filter(NotificationSeen.viewer == author.id).all()
except Exception as e:
session.rollback()
print(f"[mark_all_notifications_as_read] error: {str(e)}")
return NotificationSeenResult(error="cant mark as read")
nsr = NotificationSeenResult()
nsr.error = "cant mark as read"
return nsr
return NotificationSeenResult()