diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 45a15765..b930b6ec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,4 +17,3 @@ repos: hooks: - id: ruff args: [--fix] - - id: ruff-format diff --git a/README.md b/README.md index a783ba5b..2495d68d 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,60 @@ -# discoursio-core +## Техстек - sqlalchemy - redis - ariadne - starlette -- uvicorn +- granian -# Local development +# Локальная разработка -Install deps first +Подготовьте зависимости -on osx +osx: ``` brew install redis nginx postgres brew services start redis ``` -on debian/ubuntu +debian/ubuntu: ``` apt install redis nginx ``` -Then run nginx, redis and API server +Затем запустите postgres, redis и наш API-сервер: ```shell mkdir .venv python3.12 -m venv .venv poetry env use .venv/bin/python3.12 poetry update -poetry granian --no-ws --host 0.0.0.0 --port 8000 --interface asgi main:app +poetry granian --no-ws --host 0.0.0.0 --port 8080 --interface asgi main:app ``` -## Services +## Подключенные сервисы -### Auth +Для межсерверной коммуникации используется разны механики, похожим образом это устроено в других сервисах нашей инфраструктуры. -Setup `WEBHOOK_SECRET` env var, webhook payload on `/new-author` is expected when User is created. In front-end put the header 'Authorization' with token from signIn query or registerUser mutation. +### auth.py -### Viewed +Настройте переменную окружения WEBHOOK_SECRET и настройте webhook-полезную нагрузку на /new-author. Он ожидается при создании нового пользователя. На фронтенде включите заголовок Authorization с токеном из запроса signIn или мутации registerUser. -Set GOOGLE_ANALYTICS_TOKEN var to collect stats +### viewed.py -### Seacrh +Для статистики просмотров установите переменные окружения GOOGLE_ANALYTICS_TOKEN и GOOGLE_GA_VIEW_ID для сбора данных из Google Analytics. -ElasticSearch +### search.py -### Notifications +Результаты ElasticSearch с оценкой `score`, объединенные с запросами к базе данных, запрашиваем через GraphQL API `load_shouts_search`. -Connected using Redis PubSub channels +### notify.py -### Inbox +Отправка уведомлений по Redis PubSub каналам -To get unread counter raw redis query to Inbox's data is used +### unread.py +Счетчик непрочитанных сообщений получается через Redis-запрос к данным сервиса сообщений. -### Following Manager +### following.py -Internal service with async access to storage +Внутренний сервис, обеспечивающий асинхронный доступ к оперативному хранилищу подписчиков на комментарии, топики и авторы. diff --git a/resolvers/reader.py b/resolvers/reader.py index 39e61a2d..64a7af27 100644 --- a/resolvers/reader.py +++ b/resolvers/reader.py @@ -1,5 +1,5 @@ from sqlalchemy import bindparam, distinct, or_ -from sqlalchemy.orm import aliased, joinedload +from sqlalchemy.orm import aliased, joinedload, selectinload from sqlalchemy.sql.expression import and_, asc, case, desc, func, nulls_last, select from starlette.exceptions import HTTPException @@ -203,7 +203,7 @@ async def load_shouts_drafts(_, info): shouts = [] with local_session() as session: reader = session.query(Author).filter(Author.user == user_id).first() - if reader: + if isinstance(reader, Author): q = q.filter(Shout.created_by == reader.id) q = q.group_by(Shout.id) for [shout] in session.execute(q).unique(): @@ -370,8 +370,8 @@ async def load_shouts_unrated(_, info, limit: int = 50, offset: int = 0): q = ( select(Shout) .options( - joinedload(Shout.authors), - joinedload(Shout.topics), + selectinload(Shout.authors), + selectinload(Shout.topics), ) .outerjoin( Reaction, diff --git a/services/viewed.py b/services/viewed.py index 31d24afc..5e15876d 100644 --- a/services/viewed.py +++ b/services/viewed.py @@ -89,7 +89,7 @@ class ViewedStorage: async def update_pages(): """Запрос всех страниц от Google Analytics, отсортированных по количеству просмотров""" self = ViewedStorage - if not self.disabled and GOOGLE_GA_VIEW_ID: + if not self.disabled and bool(GOOGLE_GA_VIEW_ID): logger.info(' ⎧ Обновление данных просмотров от Google Analytics ---') try: start = time.time()