-
-
Notifications
You must be signed in to change notification settings - Fork 17
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
Users table has all users set to in_guild=False on user upsert #157
Comments
Looks like it's currently written to set all to not in the guild, then set those in the guild to true after
|
ahhh, I missed that.
Could we maybe do the whole update operation in a transaction or would
that bust some limits with regards to PostgreSQL's transaction memory?
Maybe alternatively we could collect the IDs of all users where we set
it to true and then do a single (batch of) updates after the initial
sync to set `in_guild=False` for anyone who's not in that set.
|
Closes #157 Previously we set all users in_guild to False, and relied on users being set back to in_guild when iterating through guild.members However, this caused two problems 1. For a short window a users in_guild status was incorrect 2. It required an update for all users in_guild to be sent to postgres to update in_guild back to True. This diff changes that, so instead only users who are not found in the guild have in_guild set to False
#159 seems like a way we could fix this. I haven't been able to test that postgres is ok about serialising that many strings in a single query though. |
|
My only thoughts on how to make the above PR work would be to create a Can't look into how to achieve that with SQLAlchemy right now though. |
It might be easiest to select all in guild users from the database and then do It's not quite as nice as doing it all on the database but in practice I don't think it makes a difference for our case. |
Won't this run into the same parameter issue? I have an alternative idea, although it might be a bit crazy: First we sort the list of user IDs to update ascending. Then we move the data in chunks, with special handling for the first and last chunk to incorporate an update for anything outside our known range as well. Pseudocode (unsure of the exact SQLAlchemy syntax): async with async_session() as sess:
total = len(in_guild_user_id_chunks)
for idx, chunk in enumerate(in_guild_user_id_chunks):
not_user_in_chunk = ~models.User.id.in_(chunk)
user_below_upper_bound = models.User.id <= max(chunk)
user_above_lower_bound = models.User.id >= min(chunk)
if idx == 0:
# Update the complete lower end we are aware of
condition = (user_below_upper_bound & not_user_in_chunk)
elif idx == total - 1:
# Update the complete upper end we are aware of
condition = (user_above_lower_bound & not_user_in_chunk)
else:
# Just update this batch
condition = (user_below_upper_bound & user_above_lower_bound & not_user_in_chunk)
await sess.execute(update(models.User).where(condition).values(in_guild=False))
await sess.commit() Things to consider:
|
My suggestion was to do the comparison against async with async_session() as sess:
in_guild_users = await sess.execute(select(models.User).filter_by(in_guild=True)).scalars().all()
guild_member_ids = {member.id for member in guild.members}
for user in in_guild_users:
if user.id not in guild_member_ids:
user.in_guild = False
await sess.commit() |
Chris has fixed this upstream in python-discord/metricity#157.
Chris has fixed this upstream in python-discord/metricity#157.
Chris has fixed this upstream in python-discord/metricity#157.
Chris has fixed this upstream in python-discord/metricity#157.
Chris has fixed this upstream in python-discord/metricity#157.
When metricity starts up and synchronizes the users, all users temporarily have
their
in_guild
field set tofalse
.From looking at the code I am currently unsure how this can happen. As far as I
understand, the complete upsert is run in a transaction that is committed at
the end of each individual insert.
Demonstration as taken during a metricity restart (whilst
User upsert:
messages can be seen in the logs):
The text was updated successfully, but these errors were encountered: