This commit is contained in:
parent
391958e60c
commit
2eaefaa62f
4
main.py
4
main.py
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user