-
-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix some cache bugs and ensure member is always returned on delete calls #892
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Several cache bugfixes | ||
- `CacheImpl.clear_members` and `CacheImpl.delete_member` only returning the members that have been fully deleted | ||
- This was contrary to all the other methods were the objects would be returned regardlesss of the internal references to it | ||
- `CacheImpl.clear_voice_states_for_channel` not actually deleting the voice states |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -799,7 +799,7 @@ def _garbage_collect_member( | |
*, | ||
decrement: typing.Optional[int] = None, | ||
deleting: bool = False, | ||
) -> typing.Optional[cache_utility.RefCell[cache_utility.MemberData]]: | ||
) -> None: | ||
if deleting: | ||
member.object.has_been_deleted = True | ||
|
||
|
@@ -808,10 +808,10 @@ def _garbage_collect_member( | |
|
||
user_id = member.object.user.object.id | ||
if not guild_record.members or user_id not in guild_record.members: | ||
return None | ||
return | ||
|
||
if not self._can_remove_member(member): | ||
return None | ||
return | ||
|
||
del guild_record.members[user_id] | ||
self._garbage_collect_user(member.object.user, decrement=1) | ||
|
@@ -820,8 +820,6 @@ def _garbage_collect_member( | |
guild_record.members = None | ||
self._remove_guild_record_if_empty(member.object.guild_id, guild_record) | ||
|
||
return member | ||
|
||
def clear_members( | ||
self, | ||
) -> cache.CacheView[snowflakes.Snowflake, cache.CacheView[snowflakes.Snowflake, guilds.Member]]: | ||
|
@@ -843,9 +841,10 @@ def clear_members_for_guild( | |
return cache_utility.EmptyCacheView() | ||
|
||
cached_members = guild_record.members.freeze() | ||
members_gen = (self._garbage_collect_member(guild_record, m, deleting=True) for m in cached_members.values()) | ||
# _garbage_collect_member will only return the member data object if they could be removed, else None. | ||
cached_members = {member.object.user.object.id: member for member in members_gen if member} | ||
|
||
for m in cached_members.values(): | ||
self._garbage_collect_member(guild_record, m, deleting=True) | ||
|
||
self._remove_guild_record_if_empty(guild_id, guild_record) | ||
return cache_utility.CacheMappingView(cached_members, builder=self._build_member) # type: ignore[type-var] | ||
|
||
|
@@ -868,13 +867,8 @@ def delete_member( | |
if not member_data: | ||
return None | ||
|
||
if not guild_record.members: | ||
guild_record.members = None | ||
self._remove_guild_record_if_empty(guild_id, guild_record) | ||
|
||
# _garbage_collect_member will only return the member data object if they could be removed, else None. | ||
garbage_collected = self._garbage_collect_member(guild_record, member_data, deleting=True) | ||
return self._build_member(member_data) if garbage_collected else None | ||
self._garbage_collect_member(guild_record, member_data, deleting=True) | ||
return self._build_member(member_data) | ||
|
||
def get_member( | ||
self, | ||
|
@@ -1297,8 +1291,9 @@ def clear_voice_states_for_channel( | |
|
||
cached_voice_states = {} | ||
|
||
for user_id, voice_state in guild_record.voice_states.items(): | ||
for user_id, voice_state in tuple(guild_record.voice_states.items()): | ||
if voice_state.channel_id == channel_id: | ||
del guild_record.voice_states[user_id] | ||
cached_voice_states[user_id] = voice_state | ||
self._garbage_collect_member(guild_record, voice_state.member, decrement=1) | ||
|
||
|
@@ -1348,11 +1343,12 @@ def delete_voice_state( | |
if not voice_state_data: | ||
return None | ||
|
||
self._garbage_collect_member(guild_record, voice_state_data.member, decrement=1) | ||
|
||
if not guild_record.voice_states: | ||
guild_record.voice_states = None | ||
self._remove_guild_record_if_empty(guild_id, guild_record) | ||
|
||
FasterSpeeding marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self._garbage_collect_member(guild_record, voice_state_data.member, decrement=1) | ||
self._remove_guild_record_if_empty(guild_id, guild_record) | ||
return self._build_voice_state(voice_state_data) | ||
|
||
def get_voice_state( | ||
|
@@ -1459,12 +1455,13 @@ def _garbage_collect_message( | |
*, | ||
decrement: typing.Optional[int] = None, | ||
override_ref: bool = False, | ||
) -> typing.Optional[cache_utility.RefCell[cache_utility.MessageData]]: | ||
) -> bool: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change seems unnecessary and breaks the standard pattern for these methods There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other methods currently only return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The methods which were previously only returning None are doing this because they have no relevant delete and clear methods, they are not the same case There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Look at how clear members was using it before |
||
# A bool is returned to inform whether the message was removed or not | ||
if decrement is not None: | ||
self._increment_ref_count(message, -decrement) | ||
|
||
if not self._can_remove_message(message) or override_ref: | ||
return None | ||
return False | ||
|
||
self._garbage_collect_user(message.object.author, decrement=1) | ||
|
||
|
@@ -1485,7 +1482,7 @@ def _garbage_collect_message( | |
if message.object.id in self._referenced_messages: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should return None/False/whatever you feel like if it was already marked as deleted There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The uses for this function stay the same, so either its a bug I didnt fix or I did in fact miss something. I dont get the point for an extra return tho There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clear and delete methods should only be returning objects which were actually marked as deleted not objects which were only being kept alive by references |
||
del self._referenced_messages[message.object.id] | ||
|
||
return message | ||
return True | ||
|
||
def _on_message_expire(self, message: cache_utility.RefCell[cache_utility.MessageData], /) -> None: | ||
if not self._garbage_collect_message(message): | ||
|
@@ -1520,7 +1517,6 @@ def delete_message( | |
|
||
if not self._garbage_collect_message(message_data): | ||
self._referenced_messages[message_id] = message_data | ||
return None | ||
|
||
return self._build_message(message_data) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should probably just change this to return the object if it wasn't originally marked as has_been_deleted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I changed this to not return anything is because there is no need, as the information we return in the same as the one we take in. The cases we use this for atm don't even need what we return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear and delete methods should only be returning objects which were actually marked as deleted not objects which were only being kept alive by references, the way you've changed the semantics still leads to erroneous behaviour and simply changing the behaviour of the garbage collect method will instruct both the delete and clear methods on what they should be saying was deleted and avoids a ton of other code changes