This commit is contained in:
parent
d1cd69eb2a
commit
b802bb029a
|
@ -307,6 +307,7 @@ async def delete_reaction(_, info, reaction_id: int):
|
||||||
session.delete(r)
|
session.delete(r)
|
||||||
session.commit()
|
session.commit()
|
||||||
await notify_reaction(reaction_dict, 'delete')
|
await notify_reaction(reaction_dict, 'delete')
|
||||||
|
|
||||||
return {'error': None, 'reaction': reaction_dict}
|
return {'error': None, 'reaction': reaction_dict}
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
return {'error': f'cannot delete reaction: {exc}'}
|
return {'error': f'cannot delete reaction: {exc}'}
|
||||||
|
|
|
@ -17,9 +17,10 @@ def add_topic_stat_columns(q):
|
||||||
aliased_shout_author = aliased(ShoutAuthor)
|
aliased_shout_author = aliased(ShoutAuthor)
|
||||||
aliased_topic_follower = aliased(TopicFollower)
|
aliased_topic_follower = aliased(TopicFollower)
|
||||||
aliased_shout_topic = aliased(ShoutTopic)
|
aliased_shout_topic = aliased(ShoutTopic)
|
||||||
|
aliased_shout = aliased(Shout)
|
||||||
|
|
||||||
q = (
|
q = (
|
||||||
q.outerjoin(aliased_shout_topic, aliased_shout_topic.topic == Topic.id)
|
q.outerjoin(aliased_shout_topic, and_(aliased_shout_topic.topic == Topic.id, aliased_shout.published_at.is_not(None)))
|
||||||
.add_columns(
|
.add_columns(
|
||||||
func.count(distinct(aliased_shout_topic.shout)).label('shouts_stat')
|
func.count(distinct(aliased_shout_topic.shout)).label('shouts_stat')
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,20 +24,67 @@ async def set_author_cache(author: dict):
|
||||||
await redis.execute('SET', f'user:{author.get("user")}', payload)
|
await redis.execute('SET', f'user:{author.get("user")}', payload)
|
||||||
await redis.execute('SET', f'author:{author.get("id")}', payload)
|
await redis.execute('SET', f'author:{author.get("id")}', payload)
|
||||||
|
|
||||||
|
# update stat all field for followers' caches in <authors> list
|
||||||
|
followers_str = await redis.execute('GET', f'author:{author.get("id")}:followers')
|
||||||
|
followers = []
|
||||||
|
if followers_str:
|
||||||
|
followers = json.loads(followers_str)
|
||||||
|
if isinstance(followers, list):
|
||||||
|
for follower in followers:
|
||||||
|
follower_follows_authors = []
|
||||||
|
follower_follows_authors_str = await redis.execute('GET', f'author:{author.get("id")}:follows-authors')
|
||||||
|
if follower_follows_authors_str:
|
||||||
|
follower_follows_authors = json.loads(follower_follows_authors_str)
|
||||||
|
c = 0
|
||||||
|
for old_author in follower_follows_authors:
|
||||||
|
if int(old_author.get('id')) == int(author.get('id', 0)):
|
||||||
|
follower_follows_authors[c] = author
|
||||||
|
break # exit the loop since we found and updated the author
|
||||||
|
c += 1
|
||||||
|
else:
|
||||||
|
# author not found in the list, so add the new author with the updated stat field
|
||||||
|
follower_follows_authors.append(author)
|
||||||
|
|
||||||
|
# update stat field for all authors' caches in <followers> list
|
||||||
|
follows_str = await redis.execute('GET', f'author:{author.get("id")}:follows-authors')
|
||||||
|
follows_authors = []
|
||||||
|
if follows_str:
|
||||||
|
follows_authors = json.loads(follows_str)
|
||||||
|
if isinstance(follows_authors, list):
|
||||||
|
for followed_author in follows_authors:
|
||||||
|
followed_author_followers = []
|
||||||
|
followed_author_followers_str = await redis.execute('GET', f'author:{author.get("id")}:followers')
|
||||||
|
if followed_author_followers_str:
|
||||||
|
followed_author_followers = json.loads(followed_author_followers_str)
|
||||||
|
c = 0
|
||||||
|
for old_follower in followed_author_followers:
|
||||||
|
if int(old_follower.get('id')) == int(author.get('id', 0)):
|
||||||
|
followed_author_followers[c] = author
|
||||||
|
break # exit the loop since we found and updated the author
|
||||||
|
c += 1
|
||||||
|
else:
|
||||||
|
# author not found in the list, so add the new author with the updated stat field
|
||||||
|
followed_author_followers.append(author)
|
||||||
|
|
||||||
|
async def update_author_followers_cache(author_id: int, followers):
|
||||||
|
updated_followers = [f.dict() if isinstance(f, Author) else f for f in followers]
|
||||||
|
payload = json.dumps(
|
||||||
|
updated_followers,
|
||||||
|
cls=CustomJSONEncoder,
|
||||||
|
)
|
||||||
|
await redis.execute('SET', f'author:{author_id}:followers', payload)
|
||||||
|
author_str = await redis.execute('GET', f'author:{author_id}')
|
||||||
|
if author_str:
|
||||||
|
author = json.loads(author_str)
|
||||||
|
author['stat']['followers'] = len(updated_followers)
|
||||||
|
await set_author_cache(author)
|
||||||
|
|
||||||
|
|
||||||
async def set_topic_cache(topic: dict):
|
async def set_topic_cache(topic: dict):
|
||||||
payload = json.dumps(topic, cls=CustomJSONEncoder)
|
payload = json.dumps(topic, cls=CustomJSONEncoder)
|
||||||
await redis.execute('SET', f'topic:{topic.get("id")}', payload)
|
await redis.execute('SET', f'topic:{topic.get("id")}', payload)
|
||||||
|
|
||||||
|
|
||||||
async def update_author_followers_cache(author_id: int, followers):
|
|
||||||
payload = json.dumps(
|
|
||||||
[f.dict() if isinstance(f, Author) else f for f in followers],
|
|
||||||
cls=CustomJSONEncoder,
|
|
||||||
)
|
|
||||||
await redis.execute('SET', f'author:{author_id}:followers', payload)
|
|
||||||
|
|
||||||
|
|
||||||
async def set_follows_topics_cache(follows, author_id: int):
|
async def set_follows_topics_cache(follows, author_id: int):
|
||||||
try:
|
try:
|
||||||
payload = json.dumps(
|
payload = json.dumps(
|
||||||
|
@ -54,12 +101,19 @@ async def set_follows_topics_cache(follows, author_id: int):
|
||||||
|
|
||||||
|
|
||||||
async def set_follows_authors_cache(follows, author_id: int):
|
async def set_follows_authors_cache(follows, author_id: int):
|
||||||
|
updated_follows = [a.dict() if isinstance(a, Author) else a for a in follows]
|
||||||
try:
|
try:
|
||||||
payload = json.dumps(
|
payload = json.dumps(
|
||||||
[a.dict() if isinstance(a, Author) else a for a in follows],
|
updated_follows,
|
||||||
cls=CustomJSONEncoder,
|
cls=CustomJSONEncoder,
|
||||||
)
|
)
|
||||||
await redis.execute('SET', f'author:{author_id}:follows-authors', payload)
|
await redis.execute('SET', f'author:{author_id}:follows-authors', payload)
|
||||||
|
# update author everywhere
|
||||||
|
author_str = await redis.execute('GET', f'author:{author_id}')
|
||||||
|
if author_str:
|
||||||
|
author = json.loads(author_str)
|
||||||
|
author['stat']['authors'] = len(updated_follows)
|
||||||
|
await set_author_cache(author)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
@ -110,12 +164,13 @@ async def update_followers_for_author(
|
||||||
|
|
||||||
|
|
||||||
def after_shout_update(_mapper, _connection, shout: Shout):
|
def after_shout_update(_mapper, _connection, shout: Shout):
|
||||||
|
logger.info('after shout update')
|
||||||
# Main query to get authors associated with the shout through ShoutAuthor
|
# Main query to get authors associated with the shout through ShoutAuthor
|
||||||
authors_query = (
|
authors_query = (
|
||||||
select(Author)
|
select(Author)
|
||||||
.select_from(ShoutAuthor) # Select from ShoutAuthor
|
.select_from(ShoutAuthor) # Select from ShoutAuthor
|
||||||
.join(Author, Author.id == ShoutAuthor.author) # Join with Author
|
.join(Author, Author.id == ShoutAuthor.author) # Join with Author
|
||||||
.where(ShoutAuthor.shout == shout.id) # Filter by shout.id
|
.filter(ShoutAuthor.shout == shout.id) # Filter by shout.id
|
||||||
)
|
)
|
||||||
|
|
||||||
for author_with_stat in get_with_stat(authors_query):
|
for author_with_stat in get_with_stat(authors_query):
|
||||||
|
@ -123,6 +178,7 @@ def after_shout_update(_mapper, _connection, shout: Shout):
|
||||||
|
|
||||||
|
|
||||||
def after_reaction_update(mapper, connection, reaction: Reaction):
|
def after_reaction_update(mapper, connection, reaction: Reaction):
|
||||||
|
logger.info('after reaction update')
|
||||||
try:
|
try:
|
||||||
author_subquery = select(Author).where(Author.id == reaction.created_by)
|
author_subquery = select(Author).where(Author.id == reaction.created_by)
|
||||||
replied_author_subquery = (
|
replied_author_subquery = (
|
||||||
|
@ -157,6 +213,7 @@ def after_reaction_update(mapper, connection, reaction: Reaction):
|
||||||
|
|
||||||
|
|
||||||
def after_author_update(_mapper, _connection, author: Author):
|
def after_author_update(_mapper, _connection, author: Author):
|
||||||
|
logger.info('after author update')
|
||||||
q = select(Author).where(Author.id == author.id)
|
q = select(Author).where(Author.id == author.id)
|
||||||
result = get_with_stat(q)
|
result = get_with_stat(q)
|
||||||
if result:
|
if result:
|
||||||
|
@ -165,24 +222,28 @@ def after_author_update(_mapper, _connection, author: Author):
|
||||||
|
|
||||||
|
|
||||||
def after_topic_follower_insert(_mapper, _connection, target: TopicFollower):
|
def after_topic_follower_insert(_mapper, _connection, target: TopicFollower):
|
||||||
|
logger.info(target)
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
handle_topic_follower_change(target.topic, target.follower, True)
|
handle_topic_follower_change(target.topic, target.follower, True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def after_topic_follower_delete(_mapper, _connection, target: TopicFollower):
|
def after_topic_follower_delete(_mapper, _connection, target: TopicFollower):
|
||||||
|
logger.info(target)
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
handle_topic_follower_change(target.topic, target.follower, False)
|
handle_topic_follower_change(target.topic, target.follower, False)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def after_author_follower_insert(_mapper, _connection, target: AuthorFollower):
|
def after_author_follower_insert(_mapper, _connection, target: AuthorFollower):
|
||||||
|
logger.info(target)
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
handle_author_follower_change(target.author, target.follower, True)
|
handle_author_follower_change(target.author, target.follower, True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def after_author_follower_delete(_mapper, _connection, target: AuthorFollower):
|
def after_author_follower_delete(_mapper, _connection, target: AuthorFollower):
|
||||||
|
logger.info(target)
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
handle_author_follower_change(target.author, target.follower, False)
|
handle_author_follower_change(target.author, target.follower, False)
|
||||||
)
|
)
|
||||||
|
@ -191,6 +252,7 @@ def after_author_follower_delete(_mapper, _connection, target: AuthorFollower):
|
||||||
async def handle_author_follower_change(
|
async def handle_author_follower_change(
|
||||||
author_id: int, follower_id: int, is_insert: bool
|
author_id: int, follower_id: int, is_insert: bool
|
||||||
):
|
):
|
||||||
|
logger.info(author_id)
|
||||||
author_query = select(Author).select_from(Author).filter(Author.id == author_id)
|
author_query = select(Author).select_from(Author).filter(Author.id == author_id)
|
||||||
[author] = get_with_stat(author_query)
|
[author] = get_with_stat(author_query)
|
||||||
follower_query = select(Author).select_from(Author).filter(Author.id == follower_id)
|
follower_query = select(Author).select_from(Author).filter(Author.id == follower_id)
|
||||||
|
@ -224,6 +286,7 @@ async def handle_author_follower_change(
|
||||||
async def handle_topic_follower_change(
|
async def handle_topic_follower_change(
|
||||||
topic_id: int, follower_id: int, is_insert: bool
|
topic_id: int, follower_id: int, is_insert: bool
|
||||||
):
|
):
|
||||||
|
logger.info(topic_id)
|
||||||
topic_query = select(Topic).filter(Topic.id == topic_id)
|
topic_query = select(Topic).filter(Topic.id == topic_id)
|
||||||
[topic] = get_with_stat(topic_query)
|
[topic] = get_with_stat(topic_query)
|
||||||
follower_query = select(Author).filter(Author.id == follower_id)
|
follower_query = select(Author).filter(Author.id == follower_id)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user