Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
synapse
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Monitor
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Maunium
synapse
Commits
11540be5
Unverified
Commit
11540be5
authored
3 years ago
by
Erik Johnston
Committed by
GitHub
3 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Fix `could not serialize access` errors for `claim_e2e_one_time_keys` (#10504)
parent
c2000ab3
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
changelog.d/10504.misc
+1
-0
1 addition, 0 deletions
changelog.d/10504.misc
synapse/storage/databases/main/end_to_end_keys.py
+126
-62
126 additions, 62 deletions
synapse/storage/databases/main/end_to_end_keys.py
with
127 additions
and
62 deletions
changelog.d/10504.misc
0 → 100644
+
1
−
0
View file @
11540be5
Reduce errors in PostgreSQL logs due to concurrent serialization errors.
This diff is collapsed.
Click to expand it.
synapse/storage/databases/main/end_to_end_keys.py
+
126
−
62
View file @
11540be5
...
@@ -755,81 +755,145 @@ class EndToEndKeyWorkerStore(EndToEndKeyBackgroundStore):
...
@@ -755,81 +755,145 @@ class EndToEndKeyWorkerStore(EndToEndKeyBackgroundStore):
"""
"""
@trace
@trace
def
_claim_e2e_one_time_keys
(
txn
):
def
_claim_e2e_one_time_key_simple
(
sql
=
(
txn
,
user_id
:
str
,
device_id
:
str
,
algorithm
:
str
"
SELECT key_id, key_json FROM e2e_one_time_keys_json
"
)
->
Optional
[
Tuple
[
str
,
str
]]:
"
WHERE user_id = ? AND device_id = ? AND algorithm = ?
"
"""
Claim OTK for device for DBs that don
'
t support RETURNING.
"
LIMIT 1
"
Returns:
A tuple of key name (algorithm + key ID) and key JSON, if an
OTK was found.
"""
sql
=
"""
SELECT key_id, key_json FROM e2e_one_time_keys_json
WHERE user_id = ? AND device_id = ? AND algorithm = ?
LIMIT 1
"""
txn
.
execute
(
sql
,
(
user_id
,
device_id
,
algorithm
))
otk_row
=
txn
.
fetchone
()
if
otk_row
is
None
:
return
None
key_id
,
key_json
=
otk_row
self
.
db_pool
.
simple_delete_one_txn
(
txn
,
table
=
"
e2e_one_time_keys_json
"
,
keyvalues
=
{
"
user_id
"
:
user_id
,
"
device_id
"
:
device_id
,
"
algorithm
"
:
algorithm
,
"
key_id
"
:
key_id
,
},
)
)
fallback_sql
=
(
self
.
_invalidate_cache_and_stream
(
"
SELECT key_id, key_json, used FROM e2e_fallback_keys_json
"
txn
,
self
.
count_e2e_one_time_keys
,
(
user_id
,
device_id
)
"
WHERE user_id = ? AND device_id = ? AND algorithm = ?
"
"
LIMIT 1
"
)
)
result
=
{}
delete
=
[]
return
f
"
{
algorithm
}
:
{
key_id
}
"
,
key_json
used_fallbacks
=
[]
for
user_id
,
device_id
,
algorithm
in
query_list
:
@trace
user_result
=
result
.
setdefault
(
user_id
,
{})
def
_claim_e2e_one_time_key_returning
(
device_result
=
user_result
.
setdefault
(
device_id
,
{})
txn
,
user_id
:
str
,
device_id
:
str
,
algorithm
:
str
txn
.
execute
(
sql
,
(
user_id
,
device_id
,
algorithm
))
)
->
Optional
[
Tuple
[
str
,
str
]]:
otk_row
=
txn
.
fetchone
()
"""
Claim OTK for device for DBs that support RETURNING.
if
otk_row
is
not
None
:
key_id
,
key_json
=
otk_row
Returns:
device_result
[
algorithm
+
"
:
"
+
key_id
]
=
key_json
A tuple of key name (algorithm + key ID) and key JSON, if an
delete
.
append
((
user_id
,
device_id
,
algorithm
,
key_id
))
OTK was found.
else
:
"""
# no one-time key available, so see if there's a fallback
# key
# We can use RETURNING to do the fetch and DELETE in once step.
txn
.
execute
(
fallback_sql
,
(
user_id
,
device_id
,
algorithm
))
sql
=
"""
fallback_row
=
txn
.
fetchone
()
DELETE FROM e2e_one_time_keys_json
if
fallback_row
is
not
None
:
WHERE user_id = ? AND device_id = ? AND algorithm = ?
key_id
,
key_json
,
used
=
fallback_row
AND key_id IN (
device_result
[
algorithm
+
"
:
"
+
key_id
]
=
key_json
SELECT key_id FROM e2e_one_time_keys_json
if
not
used
:
WHERE user_id = ? AND device_id = ? AND algorithm = ?
used_fallbacks
.
append
(
LIMIT 1
(
user_id
,
device_id
,
algorithm
,
key_id
)
)
)
RETURNING key_id, key_json
"""
# drop any one-time keys that were claimed
sql
=
(
txn
.
execute
(
"
DELETE FROM e2e_one_time_keys_json
"
sql
,
(
user_id
,
device_id
,
algorithm
,
user_id
,
device_id
,
algorithm
)
"
WHERE user_id = ? AND device_id = ? AND algorithm = ?
"
"
AND key_id = ?
"
)
)
for
user_id
,
device_id
,
algorithm
,
key_id
in
delete
:
otk_row
=
txn
.
fetchone
()
log_kv
(
if
otk_row
is
None
:
{
return
None
"
message
"
:
"
Executing claim e2e_one_time_keys transaction on database.
"
}
key_id
,
key_json
=
otk_row
)
return
f
"
{
algorithm
}
:
{
key_id
}
"
,
key_json
txn
.
execute
(
sql
,
(
user_id
,
device_id
,
algorithm
,
key_id
))
log_kv
({
"
message
"
:
"
finished executing and invalidating cache
"
})
results
=
{}
self
.
_invalidate_cache_and_stream
(
for
user_id
,
device_id
,
algorithm
in
query_list
:
txn
,
self
.
count_e2e_one_time_keys
,
(
user_id
,
device_id
)
if
self
.
database_engine
.
supports_returning
:
# If we support RETURNING clause we can use a single query that
# allows us to use autocommit mode.
_claim_e2e_one_time_key
=
_claim_e2e_one_time_key_returning
db_autocommit
=
True
else
:
_claim_e2e_one_time_key
=
_claim_e2e_one_time_key_simple
db_autocommit
=
False
row
=
await
self
.
db_pool
.
runInteraction
(
"
claim_e2e_one_time_keys
"
,
_claim_e2e_one_time_key
,
user_id
,
device_id
,
algorithm
,
db_autocommit
=
db_autocommit
,
)
if
row
:
device_results
=
results
.
setdefault
(
user_id
,
{}).
setdefault
(
device_id
,
{}
)
)
# mark fallback keys as used
device_results
[
row
[
0
]]
=
row
[
1
]
for
user_id
,
device_id
,
algorithm
,
key_id
in
used_fallbacks
:
continue
self
.
db_pool
.
simple_update_txn
(
txn
,
# No one-time key available, so see if there's a fallback
"
e2e_fallback_keys_json
"
,
# key
{
row
=
await
self
.
db_pool
.
simple_select_one
(
table
=
"
e2e_fallback_keys_json
"
,
keyvalues
=
{
"
user_id
"
:
user_id
,
"
device_id
"
:
device_id
,
"
algorithm
"
:
algorithm
,
},
retcols
=
(
"
key_id
"
,
"
key_json
"
,
"
used
"
),
desc
=
"
_get_fallback_key
"
,
allow_none
=
True
,
)
if
row
is
None
:
continue
key_id
=
row
[
"
key_id
"
]
key_json
=
row
[
"
key_json
"
]
used
=
row
[
"
used
"
]
# Mark fallback key as used if not already.
if
not
used
:
await
self
.
db_pool
.
simple_update_one
(
table
=
"
e2e_fallback_keys_json
"
,
keyvalues
=
{
"
user_id
"
:
user_id
,
"
user_id
"
:
user_id
,
"
device_id
"
:
device_id
,
"
device_id
"
:
device_id
,
"
algorithm
"
:
algorithm
,
"
algorithm
"
:
algorithm
,
"
key_id
"
:
key_id
,
"
key_id
"
:
key_id
,
},
},
{
"
used
"
:
True
},
updatevalues
=
{
"
used
"
:
True
},
desc
=
"
_get_fallback_key_set_used
"
,
)
)
self
.
_
invalidate_cache_and_stream
(
await
self
.
invalidate_cache_and_stream
(
txn
,
self
.
get_e2e_unused_fallback_key_types
,
(
user_id
,
device_id
)
"
get_e2e_unused_fallback_key_types
"
,
(
user_id
,
device_id
)
)
)
return
result
device_results
=
results
.
setdefault
(
user_id
,
{}).
setdefault
(
device_id
,
{})
device_results
[
f
"
{
algorithm
}
:
{
key_id
}
"
]
=
key_json
return
await
self
.
db_pool
.
runInteraction
(
return
results
"
claim_e2e_one_time_keys
"
,
_claim_e2e_one_time_keys
)
class
EndToEndKeyStore
(
EndToEndKeyWorkerStore
,
SQLBaseStore
):
class
EndToEndKeyStore
(
EndToEndKeyWorkerStore
,
SQLBaseStore
):
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment