core/services/following.py

128 lines
4.7 KiB
Python
Raw Normal View History

2023-02-06 13:09:26 +00:00
import asyncio
2024-02-03 09:48:36 +00:00
import logging
import time
from orm.author import AuthorFollower
from orm.shout import ShoutReactionsFollower
from orm.topic import TopicFollower
from services.db import local_session
logger = logging.getLogger('[services.following] ')
logger.setLevel(logging.DEBUG)
MODEL_CLASSES = {'author': AuthorFollower, 'topic': TopicFollower, 'shout': ShoutReactionsFollower}
2023-02-06 13:09:26 +00:00
class FollowingResult:
def __init__(self, event, kind, payload):
self.event = event
self.kind = kind
self.payload = payload
class Following:
def __init__(self, kind, uid):
2024-02-03 09:48:36 +00:00
self.kind = kind # author, topic, shout
2023-02-06 13:09:26 +00:00
self.uid = uid
2024-02-03 09:48:36 +00:00
self.queue = asyncio.Queue()
2023-02-06 13:09:26 +00:00
class FollowingManager:
lock = asyncio.Lock()
2024-02-03 09:48:36 +00:00
followers_by_kind = {'author': [], 'topic': [], 'shout': []}
authors_by_follower = {}
topics_by_follower = {}
shouts_by_follower = {}
@staticmethod
async def preload():
logger.info(' preloading started...')
ts = int(time.time())
async with FollowingManager.lock:
with local_session() as session:
# Load followers_by_kind
for kind in FollowingManager.followers_by_kind.keys():
model_class = MODEL_CLASSES[kind]
followers = session.query(model_class.follower).distinct().all()
FollowingManager.followers_by_kind[kind] = [follower[0] for follower in followers]
# Load authors_by_follower
2024-02-03 09:51:52 +00:00
c = 0
2024-02-03 09:48:36 +00:00
for following in session.query(AuthorFollower).all():
FollowingManager.authors_by_follower[following.follower] = FollowingManager.authors_by_follower.get(
following.follower, []
)
FollowingManager.authors_by_follower[following.follower].append(following.author)
2024-02-03 09:51:52 +00:00
c += 1
logger.info(f' {c} authors followings')
2024-02-03 09:48:36 +00:00
# Load topics_by_follower
2024-02-03 09:51:52 +00:00
c = 0
2024-02-03 09:48:36 +00:00
for following in session.query(TopicFollower).all():
FollowingManager.topics_by_follower[following.follower] = FollowingManager.topics_by_follower.get(
following.follower, []
)
FollowingManager.topics_by_follower[following.follower].append(following.topic)
2024-02-03 09:51:52 +00:00
c += 1
logger.info(f' {c} topics followings')
2024-02-03 09:48:36 +00:00
# Load shouts_by_follower
2024-02-03 09:51:52 +00:00
c = 0
2024-02-03 09:48:36 +00:00
for following in session.query(ShoutReactionsFollower).all():
FollowingManager.shouts_by_follower[following.follower] = FollowingManager.shouts_by_follower.get(
following.follower, []
)
FollowingManager.shouts_by_follower[following.follower].append(following.shout)
2024-02-03 09:51:52 +00:00
c += 1
logger.info(f' {c} shouts followings')
2024-02-03 09:48:36 +00:00
logger.info(f' preloading finished at {(int(time.time()) - ts)/1000} secs')
2023-02-06 13:09:26 +00:00
@staticmethod
async def register(kind, uid):
async with FollowingManager.lock:
2024-02-03 09:48:36 +00:00
if uid not in FollowingManager.followers_by_kind[kind]:
FollowingManager.followers_by_kind[kind].append(uid)
2023-02-06 13:09:26 +00:00
@staticmethod
async def remove(kind, uid):
async with FollowingManager.lock:
2024-02-03 09:48:36 +00:00
FollowingManager.followers_by_kind[kind] = [
follower for follower in FollowingManager.followers_by_kind[kind] if follower != uid
]
2023-02-06 13:09:26 +00:00
@staticmethod
async def push(kind, payload):
2023-02-20 17:38:20 +00:00
try:
async with FollowingManager.lock:
2024-02-03 09:48:36 +00:00
for entity in FollowingManager.followers_by_kind[kind]:
if payload.shout['created_by'] == entity:
await entity.queue.put(payload)
2023-02-20 17:38:20 +00:00
except Exception as e:
2024-02-03 09:48:36 +00:00
print(f'Error in push method: {e}')
@staticmethod
async def get_followers_by_kind(kind, target_id=None):
async with FollowingManager.lock:
return (
FollowingManager.followers_by_kind[kind][target_id]
if target_id
else FollowingManager.followers_by_kind[kind]
)
@staticmethod
async def get_authors_for(follower_id):
async with FollowingManager.lock:
return FollowingManager.authors_by_follower.get(follower_id, [])
@staticmethod
async def get_topics_for(follower_id):
async with FollowingManager.lock:
return FollowingManager.topics_by_follower.get(follower_id, [])
@staticmethod
async def get_shouts_for(follower_id):
async with FollowingManager.lock:
return FollowingManager.shouts_by_follower.get(follower_id, [])