init-strawberry
Some checks failed
deploy / deploy (push) Failing after 1m9s

This commit is contained in:
2023-11-26 13:18:57 +03:00
parent 8ef12063b0
commit 62c8d51c5d
13 changed files with 207 additions and 485 deletions

37
resolvers/listener.py Normal file
View File

@@ -0,0 +1,37 @@
import json
from typing import List, Dict
from orm.notification import Notification
from services.db import local_session
from services.rediscache import redis
def handle_reaction(notification: Dict[str, str | int | List[int]]):
"""создаеёт новое хранимое уведомление"""
try:
with local_session() as session:
n = Notification(**notification)
session.add(n)
session.commit(n)
except Exception as e:
session.rollback()
print(f"[listener.handle_reaction] error: {str(e)}")
def stop(pubsub):
pubsub.unsubscribe()
pubsub.close()
def start():
pubsub = redis.pubsub()
pubsub.subscribe("reaction")
try:
# Бесконечный цикл прослушивания
while True:
msg = pubsub.get_message()
handle_reaction(json.loads(msg["data"]))
except Exception:
pass
finally:
stop(pubsub)

View File

@@ -1,82 +0,0 @@
from sqlalchemy import and_, desc, select, update
from services.auth import login_required
from services.db import local_session
from services.schema import mutation, query
from orm.notification import Notification
# TODO: occurrencies?
# TODO: use of Author.id?
@query.field("loadNotifications")
@login_required
async def load_notifications(_, info, params=None):
if params is None:
params = {}
user_id = info.context["user_id"]
limit = params.get("limit", 50)
offset = params.get("offset", 0)
q = select(Notification).order_by(desc(Notification.created_at)).limit(limit).offset(offset)
notifications = []
with local_session() as session:
total_count = session.query(Notification).where(Notification.user == user_id).count()
total_unread_count = (
session.query(Notification)
.where(and_(Notification.user == user_id, Notification.seen == False)) # noqa: E712
.count()
)
for [notification] in session.execute(q):
notification.type = notification.type.name
notifications.append(notification)
return {
"notifications": notifications,
"total": total_count,
"unread": total_unread_count,
}
@mutation.field("markNotificationAsRead")
@login_required
async def mark_notification_as_read(_, info, notification_id: int):
user_id = info.context["user_id"]
with local_session() as session:
notification = (
session.query(Notification)
.where(and_(Notification.id == notification_id, Notification.user == user_id))
.one()
)
notification.seen = True
session.commit()
return {}
@mutation.field("markAllNotificationsAsRead")
@login_required
async def mark_all_notifications_as_read(_, info):
user_id = info.context["user_id"]
statement = (
update(Notification)
.where(and_(Notification.user == user_id, Notification.seen == False)) # noqa: E712
.values(seen=True)
)
with local_session() as session:
try:
session.execute(statement)
session.commit()
except Exception as e:
session.rollback()
print(f"[mark_all_notifications_as_read] error: {str(e)}")
return {}

108
resolvers/schema.py Normal file
View File

@@ -0,0 +1,108 @@
import strawberry
from sqlalchemy import and_
from orm.author import Author
from services.auth import login_required
from services.db import local_session
@strawberry.type
class NotificationSeen:
notification: int # notification id
viewer: int # author id
@strawberry.type
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
@strawberry.type
class NotificationsQueryResult:
notifications: list[Notification]
unread: int
@strawberry.type
class NotificationSeenResult:
error: str
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:
@login_required
@strawberry.field
async def load_notifications(self, info, limit: int = 50, offset: int = 0) -> dict:
"""непрочитанные уведомления"""
user_id = info.context["user_id"]
with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first()
nslist = (
session.query(Notification)
.outerjoin(
NotificationSeen,
and_(NotificationSeen.viewer == author.id, NotificationSeen.notification == Notification.id),
)
.limit(limit)
.offset(offset)
.all()
)
for notification in nslist:
notification.seen_by_viewer = notification_seen_by_viewer(author.id, notification.id, session)
unread = sum(1 for n in nslist if not n.seen_by_viewer)
return {"notifications": nslist, "unread": unread}
@strawberry.type
class Mutation:
@strawberry.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:
author = session.query(Author).filter(Author.user == user_id).first()
ns = NotificationSeen({"notification": notification_id, "viewer": author.id})
session.add(ns)
session.commit()
except Exception as e:
session.rollback()
print(f"[mark_notification_as_read] error: {str(e)}")
return {}
@strawberry.mutation
@login_required
async def mark_all_notifications_as_read(self, info) -> NotificationSeenResult:
user_id = info.context["user_id"]
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()
except Exception as e:
session.rollback()
print(f"[mark_all_notifications_as_read] error: {str(e)}")
return {}
schema = strawberry.Schema(query=Query, mutation=Mutation)