query-fix
This commit is contained in:
parent
59dec8cad6
commit
e7e9089b7c
|
@ -17,4 +17,3 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: [--fix]
|
args: [--fix]
|
||||||
- id: ruff-format
|
|
||||||
|
|
43
README.md
43
README.md
|
@ -1,59 +1,60 @@
|
||||||
# discoursio-core
|
## Техстек
|
||||||
|
|
||||||
|
|
||||||
- sqlalchemy
|
- sqlalchemy
|
||||||
- redis
|
- redis
|
||||||
- ariadne
|
- ariadne
|
||||||
- starlette
|
- starlette
|
||||||
- uvicorn
|
- granian
|
||||||
|
|
||||||
# Local development
|
# Локальная разработка
|
||||||
|
|
||||||
Install deps first
|
Подготовьте зависимости
|
||||||
|
|
||||||
on osx
|
osx:
|
||||||
```
|
```
|
||||||
brew install redis nginx postgres
|
brew install redis nginx postgres
|
||||||
brew services start redis
|
brew services start redis
|
||||||
```
|
```
|
||||||
|
|
||||||
on debian/ubuntu
|
debian/ubuntu:
|
||||||
```
|
```
|
||||||
apt install redis nginx
|
apt install redis nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
Then run nginx, redis and API server
|
Затем запустите postgres, redis и наш API-сервер:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir .venv
|
mkdir .venv
|
||||||
python3.12 -m venv .venv
|
python3.12 -m venv .venv
|
||||||
poetry env use .venv/bin/python3.12
|
poetry env use .venv/bin/python3.12
|
||||||
poetry update
|
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
|
Внутренний сервис, обеспечивающий асинхронный доступ к оперативному хранилищу подписчиков на комментарии, топики и авторы.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from sqlalchemy import bindparam, distinct, or_
|
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 sqlalchemy.sql.expression import and_, asc, case, desc, func, nulls_last, select
|
||||||
from starlette.exceptions import HTTPException
|
from starlette.exceptions import HTTPException
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ async def load_shouts_drafts(_, info):
|
||||||
shouts = []
|
shouts = []
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
reader = session.query(Author).filter(Author.user == user_id).first()
|
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.filter(Shout.created_by == reader.id)
|
||||||
q = q.group_by(Shout.id)
|
q = q.group_by(Shout.id)
|
||||||
for [shout] in session.execute(q).unique():
|
for [shout] in session.execute(q).unique():
|
||||||
|
@ -370,8 +370,8 @@ async def load_shouts_unrated(_, info, limit: int = 50, offset: int = 0):
|
||||||
q = (
|
q = (
|
||||||
select(Shout)
|
select(Shout)
|
||||||
.options(
|
.options(
|
||||||
joinedload(Shout.authors),
|
selectinload(Shout.authors),
|
||||||
joinedload(Shout.topics),
|
selectinload(Shout.topics),
|
||||||
)
|
)
|
||||||
.outerjoin(
|
.outerjoin(
|
||||||
Reaction,
|
Reaction,
|
||||||
|
|
|
@ -89,7 +89,7 @@ class ViewedStorage:
|
||||||
async def update_pages():
|
async def update_pages():
|
||||||
"""Запрос всех страниц от Google Analytics, отсортированных по количеству просмотров"""
|
"""Запрос всех страниц от Google Analytics, отсортированных по количеству просмотров"""
|
||||||
self = ViewedStorage
|
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 ---')
|
logger.info(' ⎧ Обновление данных просмотров от Google Analytics ---')
|
||||||
try:
|
try:
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user