This repository was archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Track and deduplicate in-flight requests to _get_state_for_groups
.
#10870
Merged
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
363565e
Add a stub implementation of `StateFilter.approx_difference`
reivilibre 1fceefd
Add method to request 1 state group, tracking the inflight request
reivilibre d998903
Add method to gather in-flight requests and calculate left-over filter
reivilibre 247f558
Add method to get 1 state group, both using and updating in-flight cache
reivilibre 7dcdab4
Use the in-flight caches for `_get_state_for_groups`
reivilibre 831a7a4
Add some basic tests about requests getting deduplicated
reivilibre 857b2d2
Newsfile
reivilibre a30042b
Convert to review comments
reivilibre cc76d9f
Use `yieldable_gather_results` helper because it's more elegant
reivilibre 58ef32e
Revert "Add a stub implementation of `StateFilter.approx_difference`"
reivilibre af85ac4
Merge remote-tracking branch 'origin/develop' into rei/gsfg_1
reivilibre f78a082
Fix up log contexts in _get_state_for_group_fire_request
reivilibre 8ea530a
Check != against StateFilter.none() for clarity
reivilibre 5352f21
Directly await fetched state for simplicity
reivilibre db840d2
Simplify gatherResults and fix log contexts
reivilibre e38f795
Merge branch 'develop' into rei/gsfg_1
reivilibre 8325ddd
Merge branch 'develop' into rei/gsfg_1
reivilibre 232be1d
Fix up misunderstanding (fixes tests)
reivilibre a3ec20c
Add licence header
reivilibre af7b61d
Simplify `super` calls
reivilibre f5321a7
Use less keyboard-feline-sounding names
reivilibre ae49d99
Update synapse/storage/databases/state/store.py
reivilibre a4ececa
Simplify the fake get_state_for_groups
reivilibre e9cb9b0
Merge branch 'develop' into rei/gsfg_1
reivilibre e2d1ea3
Use an AbstractObservableDeferred
reivilibre 61f85a0
Consume the errors from the ObservableDeferred
reivilibre 6328c65
Update tests/storage/databases/test_state_store.py
reivilibre 950a8ca
Update synapse/storage/databases/state/store.py
reivilibre f4f756a
Convert set to list before doubly iterating
reivilibre a57e7ce
Collapse for loop onto one line
reivilibre 969d45e
Use patch.object in prepare() for adding a patch
reivilibre 0d6bcef
Add docstring on test_duplicate_requests_deduplicated
reivilibre 7c2949b
Restructure _get_state_for_group_gather_inflight_requests a bit
reivilibre fcc7786
Describe the flow in the docstring
reivilibre 2c8b936
Restructure the way state is gathered to prevent building an intermed…
reivilibre 1b5cabe
Merge branch 'develop' into rei/gsfg_1
reivilibre File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Deduplicate in-flight requests in `_get_state_for_groups`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# Copyright 2022 The Matrix.org Foundation C.I.C. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
import typing | ||
from typing import Dict, List, Sequence, Tuple | ||
reivilibre marked this conversation as resolved.
Show resolved
Hide resolved
|
||
from unittest.mock import patch | ||
|
||
from twisted.internet.defer import Deferred, ensureDeferred | ||
from twisted.test.proto_helpers import MemoryReactor | ||
|
||
from synapse.storage.state import StateFilter | ||
from synapse.types import MutableStateMap, StateMap | ||
from synapse.util import Clock | ||
|
||
from tests.unittest import HomeserverTestCase | ||
|
||
if typing.TYPE_CHECKING: | ||
from synapse.server import HomeServer | ||
|
||
|
||
class StateGroupInflightCachingTestCase(HomeserverTestCase): | ||
def prepare( | ||
self, reactor: MemoryReactor, clock: Clock, homeserver: "HomeServer" | ||
) -> None: | ||
self.state_storage = homeserver.get_storage().state | ||
self.state_datastore = homeserver.get_datastores().state | ||
# Patch out the `_get_state_groups_from_groups`. | ||
# This is useful because it lets us pretend we have a slow database. | ||
reivilibre marked this conversation as resolved.
Show resolved
Hide resolved
|
||
get_state_groups_patch = patch.object( | ||
self.state_datastore, | ||
"_get_state_groups_from_groups", | ||
self._fake_get_state_groups_from_groups, | ||
) | ||
get_state_groups_patch.start() | ||
|
||
self.addCleanup(get_state_groups_patch.stop) | ||
self.get_state_group_calls: List[ | ||
Tuple[Tuple[int, ...], StateFilter, Deferred[Dict[int, StateMap[str]]]] | ||
] = [] | ||
|
||
def _fake_get_state_groups_from_groups( | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self, groups: Sequence[int], state_filter: StateFilter | ||
) -> "Deferred[Dict[int, StateMap[str]]]": | ||
d: Deferred[Dict[int, StateMap[str]]] = Deferred() | ||
self.get_state_group_calls.append((tuple(groups), state_filter, d)) | ||
return d | ||
|
||
def _complete_request_fake( | ||
self, | ||
groups: Tuple[int, ...], | ||
state_filter: StateFilter, | ||
d: "Deferred[Dict[int, StateMap[str]]]", | ||
) -> None: | ||
""" | ||
Assemble a fake database response and complete the database request. | ||
""" | ||
|
||
result: Dict[int, StateMap[str]] = {} | ||
|
||
for group in groups: | ||
group_result: MutableStateMap[str] = {} | ||
result[group] = group_result | ||
|
||
for state_type, state_keys in state_filter.types.items(): | ||
if state_keys is None: | ||
group_result[(state_type, "a")] = "xyz" | ||
group_result[(state_type, "b")] = "xyz" | ||
else: | ||
for state_key in state_keys: | ||
group_result[(state_type, state_key)] = "abc" | ||
|
||
if state_filter.include_others: | ||
group_result[("other.event.type", "state.key")] = "123" | ||
|
||
d.callback(result) | ||
|
||
def test_duplicate_requests_deduplicated(self) -> None: | ||
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 test seems nuanced enough that it could use a docstring saying what the overall steps are that are happening. 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. Added one; any good? |
||
""" | ||
Tests that duplicate requests for state are deduplicated. | ||
|
||
This test: | ||
- requests some state (state group 42, 'all' state filter) | ||
- requests it again, before the first request finishes | ||
- checks to see that only one database query was made | ||
- completes the database query | ||
- checks that both requests see the same retrieved state | ||
""" | ||
req1 = ensureDeferred( | ||
self.state_datastore._get_state_for_group_using_inflight_cache( | ||
42, StateFilter.all() | ||
) | ||
) | ||
self.pump(by=0.1) | ||
|
||
# This should have gone to the database | ||
self.assertEqual(len(self.get_state_group_calls), 1) | ||
self.assertFalse(req1.called) | ||
|
||
req2 = ensureDeferred( | ||
self.state_datastore._get_state_for_group_using_inflight_cache( | ||
42, StateFilter.all() | ||
) | ||
) | ||
self.pump(by=0.1) | ||
|
||
# No more calls should have gone to the database | ||
self.assertEqual(len(self.get_state_group_calls), 1) | ||
self.assertFalse(req1.called) | ||
self.assertFalse(req2.called) | ||
|
||
groups, sf, d = self.get_state_group_calls[0] | ||
self.assertEqual(groups, (42,)) | ||
self.assertEqual(sf, StateFilter.all()) | ||
|
||
# Now we can complete the request | ||
self._complete_request_fake(groups, sf, d) | ||
|
||
self.assertEqual( | ||
self.get_success(req1), {("other.event.type", "state.key"): "123"} | ||
) | ||
self.assertEqual( | ||
self.get_success(req2), {("other.event.type", "state.key"): "123"} | ||
) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.