Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Occasional UniqueViolation in device_lists_remote_cache_unique_id #16243

Open
DMRobertson opened this issue Sep 4, 2023 · 4 comments
Open

Occasional UniqueViolation in device_lists_remote_cache_unique_id #16243

DMRobertson opened this issue Sep 4, 2023 · 4 comments
Labels
A-Database DB stuff like queries, migrations, new/remove columns, indexes, unexpected entries in the db A-Device-List-Tracking Telling clients about other devices. Often related to E2EE. S-Minor Blocks non-critical functionality, workarounds exist. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues.

Comments

@DMRobertson
Copy link
Contributor

DMRobertson commented Sep 4, 2023

e.g.

From looking at the source, the only insert that isn't an upsert I can see is

self.db_pool.simple_insert_many_txn(
txn,
table="device_lists_remote_cache",
keys=("user_id", "device_id", "content"),
values=[
(user_id, content["device_id"], json_encoder.encode(content))
for content in devices
],
)

which might emit this error if

  • the same (user, device) ID appears twice in this batch of queries, or
  • this (user, device) pair already exists in the DB.

Tracebacks in Sentry seems to corroborate my suspicions --- they have the quoted function in their stack.

@DMRobertson DMRobertson added A-Device-List-Tracking Telling clients about other devices. Often related to E2EE. A-Database DB stuff like queries, migrations, new/remove columns, indexes, unexpected entries in the db S-Minor Blocks non-critical functionality, workarounds exist. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues. labels Sep 4, 2023
@DMRobertson
Copy link
Contributor Author

this (user, device) pair already exists in the DB.

Although you'd expect that to be ensured by

self.db_pool.simple_delete_txn(
txn, table="device_lists_remote_cache", keyvalues={"user_id": user_id}
)
if we're using REPEATABLE READ isolation

@DMRobertson
Copy link
Contributor Author

Spotted in #16138 (comment)

@erikjohnston
Copy link
Member

This is probably happening when we call that function twice at the same time, while having no existing entries in the DB. That way the DELETE is a no-op that doesn't lock any rows, so both transactions try to insert

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A-Database DB stuff like queries, migrations, new/remove columns, indexes, unexpected entries in the db A-Device-List-Tracking Telling clients about other devices. Often related to E2EE. S-Minor Blocks non-critical functionality, workarounds exist. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues.
Projects
None yet
Development

No branches or pull requests

2 participants