This commit is contained in:
parent
d0c1f33227
commit
208de158bc
|
@ -31,6 +31,15 @@ poetry env use .venv/bin/python3.12
|
||||||
poetry update
|
poetry update
|
||||||
poetry run server.py
|
poetry run server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Полезные команды
|
||||||
|
|
||||||
|
```shell
|
||||||
|
poetry run ruff check . --fix --select I # линтер и сортировка импортов
|
||||||
|
poetry run ruff format . --line-length=120 # форматирование кода
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Подключенные сервисы
|
## Подключенные сервисы
|
||||||
|
|
||||||
Для межсерверной коммуникации используются отдельные логики, папка `services/*` содержит адаптеры для использования базы данных, `redis`, кеширование и клиенты для запросов GraphQL.
|
Для межсерверной коммуникации используются отдельные логики, папка `services/*` содержит адаптеры для использования базы данных, `redis`, кеширование и клиенты для запросов GraphQL.
|
||||||
|
|
6
cache/cache.py
vendored
6
cache/cache.py
vendored
|
@ -63,14 +63,14 @@ async def update_follower_stat(follower_id, entity_type, count):
|
||||||
|
|
||||||
|
|
||||||
# Get author from cache
|
# Get author from cache
|
||||||
async def get_cached_author(author_id: int):
|
async def get_cached_author(author_id: int, get_with_stat):
|
||||||
author_key = f"author:id:{author_id}"
|
author_key = f"author:id:{author_id}"
|
||||||
result = await redis.execute("get", author_key)
|
result = await redis.execute("get", author_key)
|
||||||
if result:
|
if result:
|
||||||
return json.loads(result)
|
return json.loads(result)
|
||||||
# Load from database if not found in cache
|
# Load from database if not found in cache
|
||||||
with local_session() as session:
|
q = select(Author).where(Author.id == author_id)
|
||||||
author = session.execute(select(Author).where(Author.id == author_id)).scalar_one_or_none()
|
author = get_with_stat(q)
|
||||||
if author:
|
if author:
|
||||||
await cache_author(author.dict())
|
await cache_author(author.dict())
|
||||||
return author.dict()
|
return author.dict()
|
||||||
|
|
3
cache/revalidator.py
vendored
3
cache/revalidator.py
vendored
|
@ -1,5 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
from cache.cache import get_cached_author, cache_author, get_cached_topic, cache_topic
|
|
||||||
|
from cache.cache import cache_author, cache_topic, get_cached_author, get_cached_topic
|
||||||
from utils.logger import root_logger as logger
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
|
|
3
cache/triggers.py
vendored
3
cache/triggers.py
vendored
|
@ -1,9 +1,10 @@
|
||||||
from sqlalchemy import event
|
from sqlalchemy import event
|
||||||
|
|
||||||
|
from cache.revalidator import revalidation_manager
|
||||||
from orm.author import Author, AuthorFollower
|
from orm.author import Author, AuthorFollower
|
||||||
from orm.reaction import Reaction
|
from orm.reaction import Reaction
|
||||||
from orm.shout import Shout, ShoutAuthor, ShoutReactionsFollower
|
from orm.shout import Shout, ShoutAuthor, ShoutReactionsFollower
|
||||||
from orm.topic import Topic, TopicFollower
|
from orm.topic import Topic, TopicFollower
|
||||||
from cache.revalidator import revalidation_manager
|
|
||||||
from utils.logger import root_logger as logger
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
|
|
6
main.py
6
main.py
|
@ -7,15 +7,15 @@ from ariadne.asgi import GraphQL
|
||||||
from starlette.applications import Starlette
|
from starlette.applications import Starlette
|
||||||
from starlette.routing import Route
|
from starlette.routing import Route
|
||||||
|
|
||||||
|
from cache.precache import precache_data
|
||||||
|
from cache.revalidator import revalidation_manager
|
||||||
from services.exception import ExceptionHandlerMiddleware
|
from services.exception import ExceptionHandlerMiddleware
|
||||||
|
from services.redis import redis
|
||||||
from services.schema import resolvers
|
from services.schema import resolvers
|
||||||
from services.search import search_service
|
from services.search import search_service
|
||||||
from services.sentry import start_sentry
|
from services.sentry import start_sentry
|
||||||
from services.viewed import ViewedStorage
|
from services.viewed import ViewedStorage
|
||||||
from services.webhook import WebhookEndpoint
|
from services.webhook import WebhookEndpoint
|
||||||
from cache.precache import precache_data
|
|
||||||
from services.redis import redis
|
|
||||||
from cache.revalidator import revalidation_manager
|
|
||||||
from settings import DEV_SERVER_PID_FILE_NAME, MODE
|
from settings import DEV_SERVER_PID_FILE_NAME, MODE
|
||||||
|
|
||||||
import_module("resolvers")
|
import_module("resolvers")
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from cache.triggers import events_register
|
||||||
from resolvers.author import ( # search_authors,
|
from resolvers.author import ( # search_authors,
|
||||||
get_author,
|
get_author,
|
||||||
get_author_followers,
|
get_author_followers,
|
||||||
|
@ -22,24 +23,24 @@ from resolvers.rating import rate_author
|
||||||
from resolvers.reaction import (
|
from resolvers.reaction import (
|
||||||
create_reaction,
|
create_reaction,
|
||||||
delete_reaction,
|
delete_reaction,
|
||||||
|
load_comment_ratings,
|
||||||
load_reactions_by,
|
load_reactions_by,
|
||||||
update_reaction,
|
|
||||||
load_shout_comments,
|
load_shout_comments,
|
||||||
load_shout_ratings,
|
load_shout_ratings,
|
||||||
load_comment_ratings,
|
update_reaction,
|
||||||
)
|
)
|
||||||
from resolvers.reader import (
|
from resolvers.reader import (
|
||||||
get_shout,
|
get_shout,
|
||||||
load_shouts_by,
|
load_shouts_by,
|
||||||
|
load_shouts_coauthored,
|
||||||
|
load_shouts_discussed,
|
||||||
load_shouts_feed,
|
load_shouts_feed,
|
||||||
|
load_shouts_followed,
|
||||||
|
load_shouts_followed_by,
|
||||||
load_shouts_random_top,
|
load_shouts_random_top,
|
||||||
load_shouts_random_topic,
|
load_shouts_random_topic,
|
||||||
load_shouts_search,
|
load_shouts_search,
|
||||||
load_shouts_unrated,
|
load_shouts_unrated,
|
||||||
load_shouts_coauthored,
|
|
||||||
load_shouts_discussed,
|
|
||||||
load_shouts_followed,
|
|
||||||
load_shouts_followed_by,
|
|
||||||
)
|
)
|
||||||
from resolvers.topic import (
|
from resolvers.topic import (
|
||||||
get_topic,
|
get_topic,
|
||||||
|
@ -49,7 +50,6 @@ from resolvers.topic import (
|
||||||
get_topics_by_author,
|
get_topics_by_author,
|
||||||
get_topics_by_community,
|
get_topics_by_community,
|
||||||
)
|
)
|
||||||
from cache.triggers import events_register
|
|
||||||
|
|
||||||
events_register()
|
events_register()
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from sqlalchemy import and_, desc, select
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
from sqlalchemy.sql.functions import coalesce
|
from sqlalchemy.sql.functions import coalesce
|
||||||
|
|
||||||
|
from cache.cache import cache_author, cache_topic
|
||||||
from orm.author import Author
|
from orm.author import Author
|
||||||
from orm.rating import is_negative, is_positive
|
from orm.rating import is_negative, is_positive
|
||||||
from orm.reaction import Reaction, ReactionKind
|
from orm.reaction import Reaction, ReactionKind
|
||||||
|
@ -12,13 +13,12 @@ from orm.topic import Topic
|
||||||
from resolvers.follower import follow, unfollow
|
from resolvers.follower import follow, unfollow
|
||||||
from resolvers.stat import get_with_stat
|
from resolvers.stat import get_with_stat
|
||||||
from services.auth import login_required
|
from services.auth import login_required
|
||||||
from cache.cache import cache_author, cache_topic
|
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
from utils.diff import apply_diff, get_diff
|
|
||||||
from utils.logger import root_logger as logger
|
|
||||||
from services.notify import notify_shout
|
from services.notify import notify_shout
|
||||||
from services.schema import mutation, query
|
from services.schema import mutation, query
|
||||||
from services.search import search_service
|
from services.search import search_service
|
||||||
|
from utils.diff import apply_diff, get_diff
|
||||||
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
async def cache_by_id(entity, entity_id: int, cache_method):
|
async def cache_by_id(entity, entity_id: int, cache_method):
|
||||||
|
|
|
@ -3,6 +3,12 @@ from typing import List
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.sql import and_
|
from sqlalchemy.sql import and_
|
||||||
|
|
||||||
|
from cache.cache import (
|
||||||
|
cache_author,
|
||||||
|
cache_topic,
|
||||||
|
get_cached_follower_authors,
|
||||||
|
get_cached_follower_topics,
|
||||||
|
)
|
||||||
from orm.author import Author, AuthorFollower
|
from orm.author import Author, AuthorFollower
|
||||||
from orm.community import Community, CommunityFollower
|
from orm.community import Community, CommunityFollower
|
||||||
from orm.reaction import Reaction
|
from orm.reaction import Reaction
|
||||||
|
@ -10,7 +16,6 @@ from orm.shout import Shout, ShoutReactionsFollower
|
||||||
from orm.topic import Topic, TopicFollower
|
from orm.topic import Topic, TopicFollower
|
||||||
from resolvers.stat import get_with_stat
|
from resolvers.stat import get_with_stat
|
||||||
from services.auth import login_required
|
from services.auth import login_required
|
||||||
from cache.cache import cache_author, cache_topic, get_cached_follower_authors, get_cached_follower_topics
|
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
from services.notify import notify_follower
|
from services.notify import notify_follower
|
||||||
from services.schema import mutation, query
|
from services.schema import mutation, query
|
||||||
|
|
|
@ -8,12 +8,17 @@ from sqlalchemy.orm import aliased
|
||||||
from sqlalchemy.sql import not_
|
from sqlalchemy.sql import not_
|
||||||
|
|
||||||
from orm.author import Author
|
from orm.author import Author
|
||||||
from orm.notification import Notification, NotificationAction, NotificationEntity, NotificationSeen
|
from orm.notification import (
|
||||||
|
Notification,
|
||||||
|
NotificationAction,
|
||||||
|
NotificationEntity,
|
||||||
|
NotificationSeen,
|
||||||
|
)
|
||||||
from orm.shout import Shout
|
from orm.shout import Shout
|
||||||
from services.auth import login_required
|
from services.auth import login_required
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
from utils.logger import root_logger as logger
|
|
||||||
from services.schema import mutation, query
|
from services.schema import mutation, query
|
||||||
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
def query_notifications(author_id: int, after: int = 0) -> Tuple[int, int, List[Tuple[Notification, bool]]]:
|
def query_notifications(author_id: int, after: int = 0) -> Tuple[int, int, List[Tuple[Notification, bool]]]:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
from sqlalchemy.orm import aliased, selectinload, joinedload
|
|
||||||
|
from sqlalchemy.orm import aliased, joinedload, selectinload
|
||||||
from sqlalchemy.sql import union
|
from sqlalchemy.sql import union
|
||||||
from sqlalchemy.sql.expression import (
|
from sqlalchemy.sql.expression import (
|
||||||
and_,
|
and_,
|
||||||
|
@ -12,17 +13,18 @@ from sqlalchemy.sql.expression import (
|
||||||
select,
|
select,
|
||||||
text,
|
text,
|
||||||
)
|
)
|
||||||
|
|
||||||
from orm.author import Author, AuthorFollower
|
from orm.author import Author, AuthorFollower
|
||||||
from orm.reaction import Reaction, ReactionKind
|
from orm.reaction import Reaction, ReactionKind
|
||||||
from orm.shout import Shout, ShoutAuthor, ShoutTopic, ShoutReactionsFollower
|
from orm.shout import Shout, ShoutAuthor, ShoutReactionsFollower, ShoutTopic
|
||||||
from orm.topic import Topic, TopicFollower
|
from orm.topic import Topic, TopicFollower
|
||||||
from resolvers.topic import get_topics_random
|
from resolvers.topic import get_topics_random
|
||||||
from services.auth import login_required
|
from services.auth import login_required
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
from utils.logger import root_logger as logger
|
|
||||||
from services.schema import query
|
from services.schema import query
|
||||||
from services.search import search_text
|
from services.search import search_text
|
||||||
from services.viewed import ViewedStorage
|
from services.viewed import ViewedStorage
|
||||||
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
def query_shouts(slug=None):
|
def query_shouts(slug=None):
|
||||||
|
|
|
@ -3,8 +3,8 @@ import subprocess
|
||||||
from granian.constants import Interfaces
|
from granian.constants import Interfaces
|
||||||
from granian.server import Granian
|
from granian.server import Granian
|
||||||
|
|
||||||
from utils.logger import root_logger as logger
|
|
||||||
from settings import PORT
|
from settings import PORT
|
||||||
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
def is_docker_container_running(name):
|
def is_docker_container_running(name):
|
||||||
|
|
|
@ -2,10 +2,10 @@ from functools import wraps
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from resolvers.stat import get_with_stat
|
|
||||||
from cache.cache import get_cached_author_by_user_id
|
from cache.cache import get_cached_author_by_user_id
|
||||||
from utils.logger import root_logger as logger
|
from resolvers.stat import get_with_stat
|
||||||
from settings import ADMIN_SECRET, AUTH_URL
|
from settings import ADMIN_SECRET, AUTH_URL
|
||||||
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
async def request_data(gql, headers=None):
|
async def request_data(gql, headers=None):
|
||||||
|
|
|
@ -10,8 +10,8 @@ from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import Session, configure_mappers
|
from sqlalchemy.orm import Session, configure_mappers
|
||||||
from sqlalchemy.sql.schema import Table
|
from sqlalchemy.sql.schema import Table
|
||||||
|
|
||||||
from utils.logger import root_logger as logger
|
|
||||||
from settings import DB_URL
|
from settings import DB_URL
|
||||||
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
# from sqlalchemy_searchable import make_searchable
|
# from sqlalchemy_searchable import make_searchable
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ import json
|
||||||
|
|
||||||
from orm.notification import Notification
|
from orm.notification import Notification
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
from utils.logger import root_logger as logger
|
|
||||||
from services.redis import redis
|
from services.redis import redis
|
||||||
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
def save_notification(action: str, entity: str, payload):
|
def save_notification(action: str, entity: str, payload):
|
||||||
|
|
|
@ -5,8 +5,8 @@ import os
|
||||||
|
|
||||||
from opensearchpy import OpenSearch
|
from opensearchpy import OpenSearch
|
||||||
|
|
||||||
from utils.encoders import CustomJSONEncoder
|
|
||||||
from services.redis import redis
|
from services.redis import redis
|
||||||
|
from utils.encoders import CustomJSONEncoder
|
||||||
|
|
||||||
# Set redis logging level to suppress DEBUG messages
|
# Set redis logging level to suppress DEBUG messages
|
||||||
logger = logging.getLogger("search")
|
logger = logging.getLogger("search")
|
||||||
|
|
|
@ -2,6 +2,7 @@ import sentry_sdk
|
||||||
from sentry_sdk.integrations.ariadne import AriadneIntegration
|
from sentry_sdk.integrations.ariadne import AriadneIntegration
|
||||||
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
||||||
from sentry_sdk.integrations.starlette import StarletteIntegration
|
from sentry_sdk.integrations.starlette import StarletteIntegration
|
||||||
|
|
||||||
from settings import GLITCHTIP_DSN
|
from settings import GLITCHTIP_DSN
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,12 @@ from typing import Dict
|
||||||
|
|
||||||
# ga
|
# ga
|
||||||
from google.analytics.data_v1beta import BetaAnalyticsDataClient
|
from google.analytics.data_v1beta import BetaAnalyticsDataClient
|
||||||
from google.analytics.data_v1beta.types import DateRange, Dimension, Metric, RunReportRequest
|
from google.analytics.data_v1beta.types import (
|
||||||
|
DateRange,
|
||||||
|
Dimension,
|
||||||
|
Metric,
|
||||||
|
RunReportRequest,
|
||||||
|
)
|
||||||
|
|
||||||
from orm.author import Author
|
from orm.author import Author
|
||||||
from orm.shout import Shout, ShoutAuthor, ShoutTopic
|
from orm.shout import Shout, ShoutAuthor, ShoutTopic
|
||||||
|
|
|
@ -8,9 +8,9 @@ from starlette.exceptions import HTTPException
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
from starlette.responses import JSONResponse
|
from starlette.responses import JSONResponse
|
||||||
|
|
||||||
|
from cache.cache import cache_author
|
||||||
from orm.author import Author
|
from orm.author import Author
|
||||||
from resolvers.stat import get_with_stat
|
from resolvers.stat import get_with_stat
|
||||||
from cache.cache import cache_author
|
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user