postfixing-reimplemented-cache
All checks were successful
Deploy on push / deploy (push) Successful in 27s

This commit is contained in:
Untone 2024-05-21 02:01:18 +03:00
parent 4c1fbf64a2
commit 1592065a8c
6 changed files with 29 additions and 25 deletions

View File

@ -73,7 +73,7 @@ async def get_author(_, _info, slug="", author_id=0):
if found_author: if found_author:
logger.debug(f"found author id: {found_author.id}") logger.debug(f"found author id: {found_author.id}")
author_id = found_author.id if found_author.id else author_id author_id = found_author.id if found_author.id else author_id
author_dict = await get_cached_author(author_id) author_dict = await get_cached_author(int(author_id), get_with_stat)
# update stat from db # update stat from db
if not author_dict or not author_dict.get("stat"): if not author_dict or not author_dict.get("stat"):
@ -99,7 +99,7 @@ async def get_author_by_user_id(user_id: str):
logger.info(f"getting author id for {user_id}") logger.info(f"getting author id for {user_id}")
author = None author = None
try: try:
author = await get_cached_author_by_user_id(user_id) author = await get_cached_author_by_user_id(user_id, get_with_stat)
if author: if author:
return author return author
@ -150,7 +150,7 @@ async def load_authors_by(_, _info, by, limit, offset):
for [a] in authors_nostat: for [a] in authors_nostat:
author_dict = None author_dict = None
if isinstance(a, Author): if isinstance(a, Author):
author_dict = await get_cached_author(a.id) author_dict = await get_cached_author(a.id, get_with_stat)
if not author_dict or not isinstance(author_dict.get("shouts"), int): if not author_dict or not isinstance(author_dict.get("shouts"), int):
break break

View File

@ -135,7 +135,7 @@ async def unfollow(_, info, what, slug):
async def get_follows_by_user_id(user_id: str): async def get_follows_by_user_id(user_id: str):
if not user_id: if not user_id:
return {"error": "unauthorized"} return {"error": "unauthorized"}
author = await get_cached_author_by_user_id(user_id) author = await get_cached_author_by_user_id(user_id, get_with_stat)
if not author: if not author:
with local_session() as session: with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first() author = session.query(Author).filter(Author.user == user_id).first()

View File

@ -56,9 +56,9 @@ def get_topic_shouts_stat(topic_id: int):
return result[0] if result else 0 return result[0] if result else 0
def get_topic_authors_query(topic_id): def get_topic_authors_stat(topic_id: int):
return ( count_query = (
select(ShoutAuthor.author) select(func.count(distinct(ShoutAuthor.author)))
.select_from(join(ShoutTopic, Shout, ShoutTopic.shout == Shout.id)) .select_from(join(ShoutTopic, Shout, ShoutTopic.shout == Shout.id))
.join(ShoutAuthor, ShoutAuthor.shout == Shout.id) .join(ShoutAuthor, ShoutAuthor.shout == Shout.id)
.filter( .filter(
@ -70,14 +70,6 @@ def get_topic_authors_query(topic_id):
) )
) )
def get_topic_authors_stat(topic_id: int):
# authors query
topic_authors_query = get_topic_authors_query(topic_id)
# Оборачиваем запрос в другой запрос, чтобы посчитать уникальных авторов
count_query = select(func.count(distinct(topic_authors_query.subquery().c.author)))
# Выполняем запрос и получаем результат # Выполняем запрос и получаем результат
result = local_session().execute(count_query).scalar() result = local_session().execute(count_query).scalar()
return result if result is not None else 0 return result if result is not None else 0

View File

@ -1,7 +1,7 @@
from sqlalchemy import distinct, func, select from sqlalchemy import and_, distinct, func, join, select
from orm.author import Author from orm.author import Author
from orm.shout import ShoutTopic from orm.shout import Shout, ShoutAuthor, ShoutTopic
from orm.topic import Topic from orm.topic import Topic
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
@ -144,5 +144,17 @@ async def get_topic_authors(_, _info, slug: str):
topic_query = select(Topic.id).filter(Topic.slug == slug).first() topic_query = select(Topic.id).filter(Topic.slug == slug).first()
topic_id_result = local_session().execute(topic_query) topic_id_result = local_session().execute(topic_query)
topic_id = topic_id_result[0] if topic_id_result else None topic_id = topic_id_result[0] if topic_id_result else None
authors = await get_cached_topic_authors(topic_id) topic_authors_query = (
select(ShoutAuthor.author)
.select_from(join(ShoutTopic, Shout, ShoutTopic.shout == Shout.id))
.join(ShoutAuthor, ShoutAuthor.shout == Shout.id)
.filter(
and_(
ShoutTopic.topic == topic_id,
Shout.published_at.is_not(None),
Shout.deleted_at.is_(None),
)
)
)
authors = await get_cached_topic_authors(topic_id, topic_authors_query)
return authors return authors

View File

@ -2,6 +2,7 @@ from functools import wraps
import httpx import httpx
from resolvers.stat import get_with_stat
from services.cache import get_cached_author_by_user_id from services.cache import get_cached_author_by_user_id
from services.logger import root_logger as logger from services.logger import root_logger as logger
from settings import ADMIN_SECRET, AUTH_URL from settings import ADMIN_SECRET, AUTH_URL
@ -86,7 +87,7 @@ def login_required(f):
logger.info(f" got {user_id} roles: {user_roles}") logger.info(f" got {user_id} roles: {user_roles}")
info.context["user_id"] = user_id.strip() info.context["user_id"] = user_id.strip()
info.context["roles"] = user_roles info.context["roles"] = user_roles
author = await get_cached_author_by_user_id(user_id) author = await get_cached_author_by_user_id(user_id, get_with_stat)
if not author: if not author:
logger.error(f"author profile not found for user {user_id}") logger.error(f"author profile not found for user {user_id}")
info.context["author"] = author info.context["author"] = author

View File

@ -4,7 +4,6 @@ from sqlalchemy import and_, join, select
from orm.author import Author, AuthorFollower from orm.author import Author, AuthorFollower
from orm.topic import Topic, TopicFollower from orm.topic import Topic, TopicFollower
from resolvers.stat import get_topic_authors_query, get_with_stat
from services.db import local_session from services.db import local_session
from services.encoders import CustomJSONEncoder from services.encoders import CustomJSONEncoder
from services.logger import root_logger as logger from services.logger import root_logger as logger
@ -115,7 +114,7 @@ async def cache_follows(
return follows return follows
async def get_cached_author(author_id: int): async def get_cached_author(author_id: int, get_with_stat):
if author_id: if author_id:
rkey = f"author:id:{author_id}" rkey = f"author:id:{author_id}"
cached_result = await redis.execute("GET", rkey) cached_result = await redis.execute("GET", rkey)
@ -128,10 +127,10 @@ async def get_cached_author(author_id: int):
await cache_author(author.dict()) await cache_author(author.dict())
async def get_cached_author_by_user_id(user_id: str): async def get_cached_author_by_user_id(user_id: str, get_with_stat):
author_id = await redis.execute("GET", f"user:id:{user_id}") author_id = await redis.execute("GET", f"user:id:{user_id}")
if author_id: if author_id:
return await get_cached_author(int(author_id)) return await get_cached_author(int(author_id), get_with_stat)
async def get_cached_author_follows_topics(author_id: int): async def get_cached_author_follows_topics(author_id: int):
@ -224,7 +223,7 @@ async def get_cached_topic_followers(topic_id: int):
return followers return followers
async def get_cached_topic_authors(topic_id: int): async def get_cached_topic_authors(topic_id: int, topic_authors_query):
authors = [] authors = []
rkey = f"topic:authors:{topic_id}" rkey = f"topic:authors:{topic_id}"
cached = await redis.execute("GET", rkey) cached = await redis.execute("GET", rkey)
@ -233,7 +232,7 @@ async def get_cached_topic_authors(topic_id: int):
if isinstance(authors, list): if isinstance(authors, list):
return authors return authors
authors = local_session().execute(get_topic_authors_query(topic_id)) authors = local_session().execute(topic_authors_query)
# should be id list # should be id list
if authors: if authors:
await redis.execute("SET", rkey, json.dumps(authors)) await redis.execute("SET", rkey, json.dumps(authors))