Merge branch 'master' into 'master'

Fix of gateway mass updating

See merge request litecord/litecord!64
This commit is contained in:
Luna 2020-05-14 20:22:49 +00:00
commit a7788709df
4 changed files with 57 additions and 24 deletions

View File

@ -391,6 +391,7 @@ async def _get_billing_payments():
@bp.route("/@me/billing/payment-sources", methods=["POST"])
async def _create_payment_source():
user_id = await token_check()
j = validate(await request.get_json(), PAYMENT_SOURCE)
new_source_id = get_snowflake()

View File

@ -49,14 +49,12 @@ async def remove_member(guild_id: int, member_id: int):
("GUILD_DELETE", {"guild_id": str(guild_id), "unavailable": False}),
)
user = await app.storage.get_user(member_id)
await app.dispatcher.guild.unsub(guild_id, member_id)
await app.lazy_guild.remove_member(member_id)
await app.lazy_guild.remove_member(guild_id, user["id"])
await app.dispatcher.guild.dispatch(
guild_id,
(
"GUILD_MEMBER_REMOVE",
{"guild_id": str(guild_id), "user": await app.storage.get_user(member_id)},
),
guild_id, ("GUILD_MEMBER_REMOVE", {"guild_id": str(guild_id), "user": user},),
)

View File

@ -35,10 +35,14 @@ log = Logger(__name__)
async def mass_user_update(user_id: int) -> Tuple[dict, dict]:
"""Dispatch a USER_UPDATE to everyone that is subscribed to the user.
"""Dispatch a USER_UPDATE to the user itself
Dispatches GUILD_MEMBER_UPDATE for others sharing guilds with the user
Dispatches PRESENCE_UPDATE for friends outside of guilds
This function guarantees all states will get one USER_UPDATE for simple
cases. Lazy guild users might get updates N times depending of how many
This function guarantees all states will get one of these events for simple
cases.
Lazy guild users might get updates N times depending of how many
lists are they subscribed to.
"""
session_ids: List[str] = []
@ -46,26 +50,29 @@ async def mass_user_update(user_id: int) -> Tuple[dict, dict]:
public_user = await app.storage.get_user(user_id)
private_user = await app.storage.get_user(user_id, secure=True)
session_ids.extend(await dispatch_user(user_id, ("USER_UPDATE", private_user)))
# The user who initiated the profile change should also get possible guild events
await dispatch_user(user_id, ("USER_UPDATE", private_user))
guild_ids: List[int] = await app.user_storage.get_user_guilds(user_id)
friend_ids: List[int] = await app.user_storage.get_friend_ids(user_id)
for guild_id in guild_ids:
member = await app.storage.get_member_data_one(guild_id, user_id)
member.pop("joined_at")
session_ids.extend(
await app.dispatcher.guild.dispatch_filter(
guild_id,
lambda sess_id: sess_id not in session_ids,
("USER_UPDATE", public_user),
("GUILD_MEMBER_UPDATE", {**{"guild_id": str(guild_id)}, **member}),
)
)
for friend_id in friend_ids:
# fetch current user presence
presence = app.presence.fetch_self_presence(user_id)
# usually this presence should be partial, but there should be no major issue with a full one
session_ids.extend(
await app.dispatcher.friend.dispatch_filter(
friend_id,
lambda sess_id: sess_id not in session_ids,
("USER_UPDATE", public_user),
await app.presence.dispatch_friends_pres_filter(
public_user, lambda sess_id: sess_id not in session_ids, presence
)
)

View File

@ -199,6 +199,30 @@ class PresenceManager:
return in_lazy
async def dispatch_friends_pres(self, user_id: int, presence: BasePresence) -> None:
"""
Dispatch a new presence to all the user' friend
"""
user = await self.storage.get_user(user_id)
await app.dispatcher.friend.dispatch(
user_id, ("PRESENCE_UPDATE", {**presence.partial_dict, **{"user": user}}),
)
async def dispatch_friends_pres_filter(
self, user: dict, filter_function, presence: BasePresence
) -> None:
"""
Same as dispatch_friends_pres but passes a filter function
Takes in a whole public user object instead of a user id
"""
return await app.dispatcher.friend.dispatch_filter(
int(user["id"]),
filter_function,
("PRESENCE_UPDATE", {**presence.partial_dict, **{"user": user}}),
)
async def dispatch_pres(self, user_id: int, presence: BasePresence) -> None:
"""Dispatch a new presence to all guilds the user is in.
@ -208,11 +232,14 @@ class PresenceManager:
for guild_id in guild_ids:
await self.dispatch_guild_pres(guild_id, user_id, presence)
# dispatch to all friends that are subscribed to them
user = await self.storage.get_user(user_id)
await app.dispatcher.friend.dispatch(
user_id, ("PRESENCE_UPDATE", {**presence.partial_dict, **{"user": user}}),
)
await self.dispatch_friends_pres(user_id, presence)
def fetch_self_presence(self, user_id: int) -> BasePresence:
"""Fetch a presence for a specifc user.
This is basically the same as the friend function, so let's just call that
"""
return self.fetch_friend_presence(user_id)
def fetch_friend_presence(self, friend_id: int) -> BasePresence:
"""Fetch a presence for a friend.