upgrades
All checks were successful
deploy / deploy (push) Successful in 1m10s

This commit is contained in:
Untone 2023-12-18 01:20:13 +03:00
parent 693d8b6aee
commit 7fa6fcf2d7
7 changed files with 72 additions and 44 deletions

View File

@ -1,18 +1,18 @@
import os
import asyncio import asyncio
import os
from os.path import exists from os.path import exists
from sentry_sdk.integrations.aiohttp import AioHttpIntegration from sentry_sdk.integrations.aiohttp import AioHttpIntegration
from sentry_sdk.integrations.redis import RedisIntegration from sentry_sdk.integrations.redis import RedisIntegration
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
from sentry_sdk.integrations.strawberry import StrawberryIntegration from sentry_sdk.integrations.strawberry import StrawberryIntegration
from strawberry.asgi import GraphQL
from starlette.applications import Starlette from starlette.applications import Starlette
from strawberry.asgi import GraphQL
from services.rediscache import redis
from resolvers.listener import reactions_worker from resolvers.listener import reactions_worker
from resolvers.schema import schema from resolvers.schema import schema
from settings import DEV_SERVER_PID_FILE_NAME, SENTRY_DSN, MODE from services.rediscache import redis
from settings import DEV_SERVER_PID_FILE_NAME, MODE, SENTRY_DSN
async def start_up(): async def start_up():

View File

@ -1,6 +1,8 @@
from enum import Enum as Enumeration
import time import time
from sqlalchemy import Column, Enum, Integer, ForeignKey, JSON as JSONType from enum import Enum as Enumeration
from sqlalchemy import JSON as JSONType
from sqlalchemy import Column, Enum, ForeignKey, Integer
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from orm.author import Author from orm.author import Author

View File

@ -13,18 +13,20 @@ python = "^3.12"
SQLAlchemy = "^2.0.22" SQLAlchemy = "^2.0.22"
psycopg2-binary = "^2.9.9" psycopg2-binary = "^2.9.9"
redis = {extras = ["hiredis"], version = "^5.0.1"} redis = {extras = ["hiredis"], version = "^5.0.1"}
uvicorn = "^0.24.0.post1" uvicorn = "^0.24.0"
strawberry-graphql = {extras = ["asgi", "debug-server"], version = "^0.215.1" } strawberry-graphql = {extras = ["asgi", "debug-server"], version = "^0.216.1" }
strawberry-sqlalchemy-mapper = "^0.4.0"
sentry-sdk = "^1.37.1" sentry-sdk = "^1.37.1"
strawberry-sqlalchemy-mapper = "^0.3.1"
aiohttp = "^3.9.1" aiohttp = "^3.9.1"
[tool.poetry.dev-dependencies] [tool.poetry.group.dev.dependencies]
setuptools = "^69.0.2"
pytest = "^7.4.2" pytest = "^7.4.2"
black = { version = "^23.12.0", python = ">=3.12" } black = { version = "^23.12.0", python = ">=3.12" }
ruff = { version = "^0.1.8", python = ">=3.12" } ruff = { version = "^0.1.8", python = ">=3.12" }
mypy = { version = "^1.7", python = ">=3.12" } mypy = { version = "^1.7", python = ">=3.12" }
setuptools = "^69.0.2" isort = "^5.13.2"
pyright = "^1.1.341"
[tool.black] [tool.black]
line-length = 120 line-length = 120
@ -58,18 +60,33 @@ use_parentheses = true
ensure_newline_before_comments = true ensure_newline_before_comments = true
line_length = 120 line_length = 120
[tool.pyright] [tool.pyright]
venvPath = "." venvPath = "."
venv = ".venv" venv = ".venv"
include = ["."] include = ["."]
exclude = ["**/__pycache__"] useLibraryCodeForTypes = true
ignore = [] disableLanguageServices = false
defineConstant = { DEBUG = true } disableOrganizeImports = false
reportMissingImports = true reportMissingImports = false
reportMissingTypeStubs = false reportMissingModuleSource = "warning"
pythonVersion = "312" reportImportCycles = "warning"
pythonPlatform = "Linux" maxMemoryForLargeFile = 4096
executionEnvironments = [] pythonVersion = "3.12"
autoImportCompletions = true
useVirtualEnv = true
typeCheckingMode = "basic"
disableJediCompletion = false
disableCompletion = false
disableSnippetCompletion = false
disableGoToDefinition = false
disableRenaming = false
disableSignatureHelp = false
diagnostics = true
logLevel = "Information"
pluginSearchPaths = []
typings = {}
mergeTypeStubPackages = false
[tool.mypy] [tool.mypy]
python_version = "3.12" python_version = "3.12"

View File

@ -1,15 +1,18 @@
import logging
from typing import List from typing import List
from sqlalchemy import and_, select
from sqlalchemy.orm import aliased
from sqlalchemy.exc import SQLAlchemyError
from orm.notification import Notification as NotificationMessage, NotificationSeen import strawberry
from sqlalchemy import and_, select
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import aliased
from strawberry.schema.config import StrawberryConfig
from strawberry_sqlalchemy_mapper import StrawberrySQLAlchemyMapper
from orm.author import Author
from orm.notification import Notification as NotificationMessage
from orm.notification import NotificationSeen
from services.auth import LoginRequiredMiddleware from services.auth import LoginRequiredMiddleware
from services.db import local_session from services.db import local_session
import strawberry
from strawberry_sqlalchemy_mapper import StrawberrySQLAlchemyMapper
from strawberry.schema.config import StrawberryConfig
import logging
strawberry_sqlalchemy_mapper = StrawberrySQLAlchemyMapper() strawberry_sqlalchemy_mapper = StrawberrySQLAlchemyMapper()
@ -39,7 +42,7 @@ class NotificationsResult:
total: int total: int
def get_notifications(author_id: int, session, limit: int, offset: int) -> List[Notification]: def get_notifications(author_id: int, session, after: int, limit: int = 9999, offset: int = 0) -> List[Notification]:
NotificationSeenAlias = aliased(NotificationSeen) NotificationSeenAlias = aliased(NotificationSeen)
query = ( query = (
select(NotificationMessage, NotificationSeenAlias.viewer.label("seen")) select(NotificationMessage, NotificationSeenAlias.viewer.label("seen"))
@ -47,6 +50,7 @@ def get_notifications(author_id: int, session, limit: int, offset: int) -> List[
NotificationSeen, NotificationSeen,
and_(NotificationSeen.viewer == author_id, NotificationSeen.notification == NotificationMessage.id), and_(NotificationSeen.viewer == author_id, NotificationSeen.notification == NotificationMessage.id),
) )
.filter(NotificationMessage.created_at > after)
.group_by(NotificationSeen.notification) .group_by(NotificationSeen.notification)
) )
if limit: if limit:
@ -77,7 +81,9 @@ class Query:
with local_session() as session: with local_session() as session:
try: try:
if author_id: if author_id:
notifications = get_notifications(author_id, session, limit, offset) author = session.query(Author).filter(Author.id == author_id).first()
after = author.last_seen
notifications = get_notifications(author_id, session, after, limit, offset)
if notifications and len(notifications) > 0: if notifications and len(notifications) > 0:
nr = NotificationsResult( nr = NotificationsResult(
notifications=notifications, notifications=notifications,
@ -110,15 +116,15 @@ class Mutation:
f"[mark_notification_as_read] Ошибка при обновлении статуса прочтения уведомления: {str(e)}" f"[mark_notification_as_read] Ошибка при обновлении статуса прочтения уведомления: {str(e)}"
) )
return NotificationSeenResult(error="cant mark as read") return NotificationSeenResult(error="cant mark as read")
return NotificationSeenResult() return NotificationSeenResult(error=None)
@strawberry.mutation @strawberry.mutation
async def mark_all_notifications_as_read(self, info) -> NotificationSeenResult: async def mark_all_notifications_as_read(self, info) -> NotificationSeenResult:
author_id = info.context.get("author_id") author_id = info.context.get("author_id")
if author_id: if author_id:
try:
with local_session() as session: with local_session() as session:
nslist = get_notifications(author_id, session, None, None) try:
nslist = get_notifications(author_id, session)
for n in nslist: for n in nslist:
if author_id not in n.seen: if author_id not in n.seen:
ns = NotificationSeen(viewer=author_id, notification=n.id) ns = NotificationSeen(viewer=author_id, notification=n.id)
@ -127,10 +133,10 @@ class Mutation:
except SQLAlchemyError as e: except SQLAlchemyError as e:
session.rollback() session.rollback()
logger.error( logger.error(
f"[mark_all_notifications_as_read] Ошибка при обновлении статуса прочтения всех уведомлений: {str(e)}" f"[mark_all_notifications_as_read] Ошибка обновления статуса прочтения всех уведомлений: {e}"
) )
return NotificationSeenResult(error="cant mark as read") return NotificationSeenResult(error="cant mark as read")
return NotificationSeenResult() return NotificationSeenResult(error=None)
schema = strawberry.Schema( schema = strawberry.Schema(

View File

@ -7,7 +7,7 @@ from services.db import local_session
from settings import AUTH_URL from settings import AUTH_URL
async def check_auth(req) -> (bool, int | None): async def check_auth(req):
token = req.headers.get("Authorization") token = req.headers.get("Authorization")
if token: if token:
# Logging the authentication token # Logging the authentication token
@ -62,7 +62,7 @@ async def check_auth(req) -> (bool, int | None):
except Exception as e: except Exception as e:
# Handling and logging exceptions during authentication check # Handling and logging exceptions during authentication check
print(f"[services.auth] {e}") print(f"[services.auth] {e}")
raise HTTPUnauthorized(message="Please, login first") raise HTTPUnauthorized(text="Please, login first")
return False, None return False, None

View File

@ -1,5 +1,7 @@
from typing import List, Any from typing import Any, List
import aiohttp import aiohttp
from settings import API_BASE from settings import API_BASE
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
@ -23,7 +25,7 @@ async def _request_endpoint(query_name, body):
traceback.print_exc() traceback.print_exc()
async def get_followed_shouts(author_id: int) -> List[Any]: async def get_followed_shouts(author_id: int):
query_name = "load_shouts_followed" query_name = "load_shouts_followed"
query_type = "query" query_type = "query"
operation = "GetFollowedShouts" operation = "GetFollowedShouts"

View File

@ -2,6 +2,7 @@ import asyncio
import json import json
import redis.asyncio as aredis import redis.asyncio as aredis
from settings import REDIS_URL from settings import REDIS_URL