following-fix

This commit is contained in:
Untone 2024-04-18 12:34:04 +03:00
parent 47bc3adb69
commit 1a685e458d
4 changed files with 86 additions and 59 deletions

View File

@ -59,14 +59,17 @@ async def get_author(_, _info, slug="", author_id=0):
author_query = select(Author).filter(
or_(Author.slug == slug, Author.id == author_id)
)
[found_author] = local_session().execute(author_query).first()
lookup_result = local_session().execute(author_query).first()
if lookup_result:
[found_author] = lookup_result
logger.debug(found_author)
if found_author:
logger.debug(f"found author id: {found_author.id}")
author_id = found_author.id if found_author.id else author_id
if author_id:
cached_result = await redis.execute("GET", f"author:{author_id}")
author_dict = json.loads(cached_result) if cached_result else None
if isinstance(cached_result, str):
author_dict = json.loads(cached_result)
# update stat from db
if not author_dict or not author_dict.get("stat"):
@ -180,7 +183,7 @@ async def get_author_follows(_, _info, slug="", user=None, author_id=0):
# logger.debug(author)
if author and isinstance(author, Author):
# logger.debug(author.dict())
author_id = author.id
author_id = author.id if not author_id else author_id
rkey = f"author:{author_id}:follows-authors"
logger.debug(f"getting {author_id} follows authors")
cached = await redis.execute("GET", rkey)

View File

@ -13,7 +13,7 @@ from orm.shout import Shout, ShoutReactionsFollower
from orm.topic import Topic, TopicFollower
from resolvers.stat import author_follows_authors, author_follows_topics, get_with_stat
from services.auth import login_required
from services.cache import DEFAULT_FOLLOWS
from services.cache import DEFAULT_FOLLOWS, cache_follower
from services.db import local_session
from services.logger import root_logger as logger
from services.notify import notify_follower
@ -24,21 +24,35 @@ from services.schema import mutation, query
@mutation.field("follow")
@login_required
async def follow(_, info, what, slug):
follows = []
error = None
user_id = info.context.get("user_id")
if not user_id:
return {"error": "unauthorized"}
follower = local_session().query(Author).filter(Author.user == user_id).first()
if not follower:
return {"error": "cant find follower account"}
entity = what.lower()
follows = []
follows_str = await redis.execute("GET", f"author:{follower.id}:follows-{entity}s")
if isinstance(follows_str, str):
follows = json.loads(follows_str)
if not follower:
return {"error": "cant find follower"}
if what == "AUTHOR":
error = author_follow(follower.id, slug)
if not error:
author = local_session().query(Author).where(Author.slug == slug).first()
result = get_with_stat(select(Author).where(Author.slug == slug))
if result:
[author] = result
if author:
await cache_follower(follower, author)
await notify_follower(follower.dict(), author.id, "follow")
if not any(a["id"] == author.id for a in follows):
follows.append(author.dict())
elif what == "TOPIC":
error = topic_follow(follower.id, slug)
@ -53,10 +67,6 @@ async def follow(_, info, what, slug):
if error:
return {"error": error}
entity = what.lower()
follows_str = await redis.execute("GET", f"author:{follower.id}:follows-{entity}s")
if follows_str:
follows = json.loads(follows_str)
return {f"{entity}s": follows}
@ -68,17 +78,24 @@ async def unfollow(_, info, what, slug):
user_id = info.context.get("user_id")
if not user_id:
return {"error": "unauthorized"}
follower = local_session().query(Author).filter(Author.user == user_id).first()
if not follower:
return {"error": "follower profile is not found"}
return {"error": "cant find follower account"}
if what == "AUTHOR":
error = author_unfollow(follower.id, slug)
# NOTE: after triggers should update cached stats
if not error:
logger.info(f"@{follower.slug} unfollowed @{slug}")
author = local_session().query(Author).where(Author.slug == slug).first()
if author:
if isinstance(author, Author):
await cache_follower(follower, author, False)
await notify_follower(follower.dict(), author.id, "unfollow")
for idx, item in enumerate(follows):
if item["id"] == author.id:
follows.pop(idx) # Remove the author_dict from the follows list
break
elif what == "TOPIC":
error = topic_unfollow(follower.id, slug)
@ -91,7 +108,7 @@ async def unfollow(_, info, what, slug):
entity = what.lower()
follows_str = await redis.execute("GET", f"author:{follower.id}:follows-{entity}s")
if follows_str:
if isinstance(follows_str, str):
follows = json.loads(follows_str)
return {"error": error, f"{entity}s": follows}

View File

@ -123,7 +123,7 @@ async def _create_reaction(session, shout, author, reaction):
rdict = r.dict()
# пересчет счетчика комментариев
if r.kind == ReactionKind.COMMENT.value:
if str(r.kind) == ReactionKind.COMMENT.value:
await update_author_stat(author)
# collaborative editing
@ -151,7 +151,7 @@ async def _create_reaction(session, shout, author, reaction):
pass
# обновление счетчика комментариев в кеше
if r.kind == ReactionKind.COMMENT.value:
if str(r.kind) == ReactionKind.COMMENT.value:
await update_author_stat(author)
rdict["shout"] = shout.dict()
@ -215,7 +215,6 @@ async def create_reaction(_, info, reaction):
if shout and author:
reaction["created_by"] = author.id
kind = reaction.get("kind")
shout_id = shout.id
if not kind and isinstance(reaction.get("body"), str):
kind = ReactionKind.COMMENT.value
@ -260,14 +259,22 @@ async def update_reaction(_, info, reaction):
reaction_query = reaction_query.group_by(Reaction.id)
try:
[r, reacted_stat, commented_stat, likes_stat, dislikes_stat, _l] = (
session.execute(reaction_query).unique().first()
)
result = session.execute(reaction_query).unique().first()
if result:
[
r,
reacted_stat,
commented_stat,
likes_stat,
dislikes_stat,
last_comment,
] = result
if not r:
return {"error": "invalid reaction id"}
author = session.query(Author).filter(Author.user == user_id).first()
author = (
session.query(Author).filter(Author.user == user_id).first()
)
if author:
if r.created_by != author.id and "editor" not in roles:
return {"error": "access denied"}
@ -323,7 +330,7 @@ async def delete_reaction(_, info, reaction_id: int):
session.commit()
# обновление счетчика комментариев в кеше
if r.kind == ReactionKind.COMMENT.value:
if str(r.kind) == ReactionKind.COMMENT.value:
await update_author_stat(author)
await notify_reaction(reaction_dict, "delete")

View File

@ -29,7 +29,7 @@ async def cache_author(author: dict):
follower_follows_authors_str = await redis.execute(
"GET", f'author:{author.get("id")}:follows-authors'
)
if follower_follows_authors_str:
if isinstance(follower_follows_authors_str, str):
follower_follows_authors = json.loads(follower_follows_authors_str)
c = 0
for old_author in follower_follows_authors:
@ -46,7 +46,7 @@ async def cache_author(author: dict):
"GET", f'author:{author.get("id")}:follows-authors'
)
follows_authors = []
if follows_str:
if isinstance(follows_str, str):
follows_authors = json.loads(follows_str)
if isinstance(follows_authors, list):
for followed_author in follows_authors:
@ -54,7 +54,7 @@ async def cache_author(author: dict):
followed_author_followers_str = await redis.execute(
"GET", f'author:{author.get("id")}:followers'
)
if followed_author_followers_str:
if isinstance(followed_author_followers_str, str):
followed_author_followers = json.loads(followed_author_followers_str)
c = 0
for old_follower in followed_author_followers:
@ -90,7 +90,7 @@ async def cache_follows(follower: Author, entity_type: str, entity, is_insert=Tr
# update follower's stats everywhere
author_str = await redis.execute("GET", f"author:{follower.id}")
if author_str:
if isinstance(author_str, str):
author = json.loads(author_str)
author["stat"][f"{entity_type}s"] = len(updated_data)
await cache_author(author)
@ -114,7 +114,7 @@ async def cache_follower(follower: Author, author: Author, is_insert=True):
payload = json.dumps(updated_followers, cls=CustomJSONEncoder)
await redis.execute("SET", redis_key, payload)
author_str = await redis.execute("GET", f"author:{follower.id}")
if author_str:
if isinstance(author_str, str):
author = json.loads(author_str)
author["stat"]["followers"] = len(updated_followers)
await cache_author(author)