Compare commits

...

5 Commits

Author SHA1 Message Date
Eric Eastwood
b732dabe3d Try poetry lock --no-update again after clear caches
See https://github.com/matrix-org/synapse/pull/13399#discussion_r930442775
2022-07-26 16:55:57 -05:00
Eric Eastwood
75a751dd54 poetry.lock from develop 2022-07-26 16:32:13 -05:00
Eric Eastwood
c15e0bd54a Try poetry lock --no-update 2022-07-26 16:25:51 -05:00
Eric Eastwood
801069ae81 Draft: Try use rust-jaeger-python-client 2022-07-26 16:20:20 -05:00
Eric Eastwood
522c29bfc7 Instrument /messages for understandable traces 2022-07-22 22:29:18 -05:00
15 changed files with 115 additions and 45 deletions

View File

@@ -38,10 +38,10 @@ FROM docker.io/python:${PYTHON_VERSION}-slim as requirements
# Here we use it to set up a cache for apt (and below for pip), to improve # Here we use it to set up a cache for apt (and below for pip), to improve
# rebuild speeds on slow connections. # rebuild speeds on slow connections.
RUN \ RUN \
--mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update -qq && apt-get install -yqq git \ apt-get update -qq && apt-get install -yqq git \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# We install poetry in its own build stage to avoid its dependencies conflicting with # We install poetry in its own build stage to avoid its dependencies conflicting with
# synapse's dependencies. # synapse's dependencies.
@@ -77,22 +77,31 @@ FROM docker.io/python:${PYTHON_VERSION}-slim as builder
# install the OS build deps # install the OS build deps
RUN \ RUN \
--mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update -qq && apt-get install -yqq \ apt-get update -qq && apt-get install -yqq \
build-essential \ build-essential \
libffi-dev \ libffi-dev \
libjpeg-dev \ libjpeg-dev \
libpq-dev \ libpq-dev \
libssl-dev \ libssl-dev \
libwebp-dev \ libwebp-dev \
libxml++2.6-dev \ libxml++2.6-dev \
libxslt1-dev \ libxslt1-dev \
openssl \ openssl \
rustc \ #rustc \
zlib1g-dev \ curl \
git \ zlib1g-dev \
&& rm -rf /var/lib/apt/lists/* git \
&& rm -rf /var/lib/apt/lists/*
#RUN apt-cache policy rustc
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y
# Add .cargo/bin to PATH
ENV PATH="/root/.cargo/bin:${PATH}"
# Check cargo is visible
RUN cargo --help
# To speed up rebuilds, install all of the dependencies before we copy over # To speed up rebuilds, install all of the dependencies before we copy over
# the whole synapse project, so that this layer in the Docker cache can be # the whole synapse project, so that this layer in the Docker cache can be
@@ -123,19 +132,19 @@ LABEL org.opencontainers.image.source='https://github.com/matrix-org/synapse.git
LABEL org.opencontainers.image.licenses='Apache-2.0' LABEL org.opencontainers.image.licenses='Apache-2.0'
RUN \ RUN \
--mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update -qq && apt-get install -yqq \ apt-get update -qq && apt-get install -yqq \
curl \ curl \
gosu \ gosu \
libjpeg62-turbo \ libjpeg62-turbo \
libpq5 \ libpq5 \
libwebp6 \ libwebp6 \
xmlsec1 \ xmlsec1 \
libjemalloc2 \ libjemalloc2 \
libssl-dev \ libssl-dev \
openssl \ openssl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY --from=builder /install /usr/local COPY --from=builder /install /usr/local
COPY ./docker/start.py /start.py COPY ./docker/start.py /start.py
@@ -146,4 +155,4 @@ EXPOSE 8008/tcp 8009/tcp 8448/tcp
ENTRYPOINT ["/start.py"] ENTRYPOINT ["/start.py"]
HEALTHCHECK --start-period=5s --interval=15s --timeout=5s \ HEALTHCHECK --start-period=5s --interval=15s --timeout=5s \
CMD curl -fSs http://localhost:8008/health || exit 1 CMD curl -fSs http://localhost:8008/health || exit 1

View File

@@ -184,3 +184,18 @@ trusted_key_servers:
password_config: password_config:
enabled: true enabled: true
opentracing:
enabled: true
jaeger_config:
# Sample everything
sampler:
type: const
param: 1
# via https://github.com/jaegertracing/jaeger-client-python/issues/47#issuecomment-493497439
local_agent:
reporting_host: "host.docker.internal"
reporting_port: 6831
# Logging whether spans were started and reported
#
logging: true

36
poetry.lock generated
View File

@@ -177,7 +177,7 @@ optional = false
python-versions = "*" python-versions = "*"
[package.extras] [package.extras]
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] test = ["hypothesis (==3.55.3)", "flake8 (==3.7.8)"]
[[package]] [[package]]
name = "constantly" name = "constantly"
@@ -435,8 +435,8 @@ optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[package.extras] [package.extras]
test = ["pytest", "pytest-trio", "pytest-asyncio", "testpath", "trio", "async-timeout"] trio = ["async-generator", "trio"]
trio = ["trio", "async-generator"] test = ["async-timeout", "trio", "testpath", "pytest-asyncio", "pytest-trio", "pytest"]
[[package]] [[package]]
name = "jinja2" name = "jinja2"
@@ -535,8 +535,8 @@ attrs = "*"
importlib-metadata = {version = ">=1.4", markers = "python_version < \"3.8\""} importlib-metadata = {version = ">=1.4", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
dev = ["tox", "twisted", "aiounittest", "mypy (==0.910)", "black (==22.3.0)", "flake8 (==4.0.1)", "isort (==5.9.3)", "build (==0.8.0)", "twine (==4.0.1)"] test = ["aiounittest", "twisted", "tox"]
test = ["tox", "twisted", "aiounittest"] dev = ["twine (==4.0.1)", "build (==0.8.0)", "isort (==5.9.3)", "flake8 (==4.0.1)", "black (==22.3.0)", "mypy (==0.910)", "aiounittest", "twisted", "tox"]
[[package]] [[package]]
name = "matrix-synapse-ldap3" name = "matrix-synapse-ldap3"
@@ -552,7 +552,7 @@ service-identity = "*"
Twisted = ">=15.1.0" Twisted = ">=15.1.0"
[package.extras] [package.extras]
dev = ["matrix-synapse", "tox", "ldaptor", "mypy (==0.910)", "types-setuptools", "black (==22.3.0)", "flake8 (==4.0.1)", "isort (==5.9.3)"] dev = ["isort (==5.9.3)", "flake8 (==4.0.1)", "black (==22.3.0)", "types-setuptools", "mypy (==0.910)", "ldaptor", "tox", "matrix-synapse"]
[[package]] [[package]]
name = "mccabe" name = "mccabe"
@@ -820,10 +820,10 @@ optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[package.extras] [package.extras]
tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
docs = ["zope.interface", "sphinx-rtd-theme", "sphinx"]
dev = ["pre-commit", "mypy", "coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)", "cryptography (>=3.3.1)", "zope.interface", "sphinx-rtd-theme", "sphinx"]
crypto = ["cryptography (>=3.3.1)"] crypto = ["cryptography (>=3.3.1)"]
dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"]
docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"]
[[package]] [[package]]
name = "pymacaroons" name = "pymacaroons"
@@ -1007,6 +1007,21 @@ python-versions = ">=3.7"
[package.extras] [package.extras]
idna2008 = ["idna"] idna2008 = ["idna"]
[[package]]
name = "rust-python-jaeger-reporter"
version = "0.1.20"
description = "A faster reporter for the python `jaeger-client` that reports spans in a native background thread."
category = "main"
optional = false
python-versions = ">=3.6"
develop = false
[package.source]
type = "git"
url = "https://github.com/erikjohnston/rust-jaeger-python-client.git"
reference = "master"
resolved_reference = "27754b5f56b4099374c389f677911f7af852a00e"
[[package]] [[package]]
name = "secretstorage" name = "secretstorage"
version = "3.3.1" version = "3.3.1"
@@ -1563,7 +1578,7 @@ url_preview = ["lxml"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.7.1" python-versions = "^3.7.1"
content-hash = "c24bbcee7e86dbbe7cdbf49f91a25b310bf21095452641e7440129f59b077f78" content-hash = "0fc4f4fc7606ac12a18e1e5657f0f45cfa46442d46053ea106e0e28c53bcbaaf"
[metadata.files] [metadata.files]
attrs = [ attrs = [
@@ -2394,6 +2409,7 @@ rfc3986 = [
{file = "rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd"}, {file = "rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd"},
{file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"}, {file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"},
] ]
rust-python-jaeger-reporter = []
secretstorage = [ secretstorage = [
{file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"}, {file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"},
{file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"}, {file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"},

View File

@@ -182,6 +182,7 @@ hiredis = { version = "*", optional = true }
Pympler = { version = "*", optional = true } Pympler = { version = "*", optional = true }
parameterized = { version = ">=0.7.4", optional = true } parameterized = { version = ">=0.7.4", optional = true }
idna = { version = ">=2.5", optional = true } idna = { version = ">=2.5", optional = true }
rust-python-jaeger-reporter = {git = "https://github.com/erikjohnston/rust-jaeger-python-client.git"}
[tool.poetry.extras] [tool.poetry.extras]
# NB: Packages that should be part of `pip install matrix-synapse[all]` need to be specified # NB: Packages that should be part of `pip install matrix-synapse[all]` need to be specified

View File

@@ -101,6 +101,7 @@ if [ -z "$skip_docker_build" ]; then
echo_if_github "::group::Build Docker image: matrixdotorg/synapse" echo_if_github "::group::Build Docker image: matrixdotorg/synapse"
docker build -t matrixdotorg/synapse \ docker build -t matrixdotorg/synapse \
--build-arg TEST_ONLY_SKIP_DEP_HASH_VERIFICATION \ --build-arg TEST_ONLY_SKIP_DEP_HASH_VERIFICATION \
--progress=plain \
-f "docker/Dockerfile" . -f "docker/Dockerfile" .
echo_if_github "::endgroup::" echo_if_github "::endgroup::"

View File

@@ -30,7 +30,12 @@ from synapse.api.errors import (
from synapse.appservice import ApplicationService from synapse.appservice import ApplicationService
from synapse.http import get_request_user_agent from synapse.http import get_request_user_agent
from synapse.http.site import SynapseRequest from synapse.http.site import SynapseRequest
from synapse.logging.opentracing import active_span, force_tracing, start_active_span from synapse.logging.opentracing import (
active_span,
force_tracing,
start_active_span,
trace,
)
from synapse.storage.databases.main.registration import TokenLookupResult from synapse.storage.databases.main.registration import TokenLookupResult
from synapse.types import Requester, UserID, create_requester from synapse.types import Requester, UserID, create_requester
@@ -563,6 +568,7 @@ class Auth:
return query_params[0].decode("ascii") return query_params[0].decode("ascii")
@trace
async def check_user_in_room_or_world_readable( async def check_user_in_room_or_world_readable(
self, room_id: str, user_id: str, allow_departed_users: bool = False self, room_id: str, user_id: str, allow_departed_users: bool = False
) -> Tuple[str, Optional[str]]: ) -> Tuple[str, Optional[str]]:

View File

@@ -61,6 +61,7 @@ from synapse.federation.federation_base import (
) )
from synapse.federation.transport.client import SendJoinResponse from synapse.federation.transport.client import SendJoinResponse
from synapse.http.types import QueryParams from synapse.http.types import QueryParams
from synapse.logging.opentracing import trace
from synapse.types import JsonDict, UserID, get_domain_from_id from synapse.types import JsonDict, UserID, get_domain_from_id
from synapse.util.async_helpers import concurrently_execute from synapse.util.async_helpers import concurrently_execute
from synapse.util.caches.expiringcache import ExpiringCache from synapse.util.caches.expiringcache import ExpiringCache
@@ -233,6 +234,7 @@ class FederationClient(FederationBase):
destination, content, timeout destination, content, timeout
) )
@trace
async def backfill( async def backfill(
self, dest: str, room_id: str, limit: int, extremities: Collection[str] self, dest: str, room_id: str, limit: int, extremities: Collection[str]
) -> Optional[List[EventBase]]: ) -> Optional[List[EventBase]]:

View File

@@ -59,6 +59,7 @@ from synapse.events.validator import EventValidator
from synapse.federation.federation_client import InvalidResponseError from synapse.federation.federation_client import InvalidResponseError
from synapse.http.servlet import assert_params_in_dict from synapse.http.servlet import assert_params_in_dict
from synapse.logging.context import nested_logging_context from synapse.logging.context import nested_logging_context
from synapse.logging.opentracing import trace
from synapse.metrics.background_process_metrics import run_as_background_process from synapse.metrics.background_process_metrics import run_as_background_process
from synapse.module_api import NOT_SPAM from synapse.module_api import NOT_SPAM
from synapse.replication.http.federation import ( from synapse.replication.http.federation import (
@@ -180,6 +181,7 @@ class FederationHandler:
"resume_sync_partial_state_room", self._resume_sync_partial_state_room "resume_sync_partial_state_room", self._resume_sync_partial_state_room
) )
@trace
async def maybe_backfill( async def maybe_backfill(
self, room_id: str, current_depth: int, limit: int self, room_id: str, current_depth: int, limit: int
) -> bool: ) -> bool:

View File

@@ -59,6 +59,7 @@ from synapse.events import EventBase
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
from synapse.federation.federation_client import InvalidResponseError from synapse.federation.federation_client import InvalidResponseError
from synapse.logging.context import nested_logging_context from synapse.logging.context import nested_logging_context
from synapse.logging.opentracing import trace
from synapse.metrics.background_process_metrics import run_as_background_process from synapse.metrics.background_process_metrics import run_as_background_process
from synapse.replication.http.devices import ReplicationUserDevicesResyncRestServlet from synapse.replication.http.devices import ReplicationUserDevicesResyncRestServlet
from synapse.replication.http.federation import ( from synapse.replication.http.federation import (
@@ -560,6 +561,7 @@ class FederationEventHandler:
event.event_id event.event_id
) )
@trace
async def backfill( async def backfill(
self, dest: str, room_id: str, limit: int, extremities: Collection[str] self, dest: str, room_id: str, limit: int, extremities: Collection[str]
) -> None: ) -> None:
@@ -604,6 +606,7 @@ class FederationEventHandler:
backfilled=True, backfilled=True,
) )
@trace
async def _get_missing_events_for_pdu( async def _get_missing_events_for_pdu(
self, origin: str, pdu: EventBase, prevs: Set[str], min_depth: int self, origin: str, pdu: EventBase, prevs: Set[str], min_depth: int
) -> None: ) -> None:
@@ -704,6 +707,7 @@ class FederationEventHandler:
logger.info("Got %d prev_events", len(missing_events)) logger.info("Got %d prev_events", len(missing_events))
await self._process_pulled_events(origin, missing_events, backfilled=False) await self._process_pulled_events(origin, missing_events, backfilled=False)
@trace
async def _process_pulled_events( async def _process_pulled_events(
self, origin: str, events: Iterable[EventBase], backfilled: bool self, origin: str, events: Iterable[EventBase], backfilled: bool
) -> None: ) -> None:
@@ -742,6 +746,7 @@ class FederationEventHandler:
with nested_logging_context(ev.event_id): with nested_logging_context(ev.event_id):
await self._process_pulled_event(origin, ev, backfilled=backfilled) await self._process_pulled_event(origin, ev, backfilled=backfilled)
@trace
async def _process_pulled_event( async def _process_pulled_event(
self, origin: str, event: EventBase, backfilled: bool self, origin: str, event: EventBase, backfilled: bool
) -> None: ) -> None:

View File

@@ -24,6 +24,7 @@ from synapse.api.errors import SynapseError
from synapse.api.filtering import Filter from synapse.api.filtering import Filter
from synapse.events.utils import SerializeEventConfig from synapse.events.utils import SerializeEventConfig
from synapse.handlers.room import ShutdownRoomResponse from synapse.handlers.room import ShutdownRoomResponse
from synapse.logging.opentracing import trace
from synapse.metrics.background_process_metrics import run_as_background_process from synapse.metrics.background_process_metrics import run_as_background_process
from synapse.storage.state import StateFilter from synapse.storage.state import StateFilter
from synapse.streams.config import PaginationConfig from synapse.streams.config import PaginationConfig
@@ -416,6 +417,7 @@ class PaginationHandler:
await self._storage_controllers.purge_events.purge_room(room_id) await self._storage_controllers.purge_events.purge_room(room_id)
@trace
async def get_messages( async def get_messages(
self, self,
requester: Requester, requester: Requester,

View File

@@ -19,6 +19,7 @@ import attr
from synapse.api.constants import RelationTypes from synapse.api.constants import RelationTypes
from synapse.api.errors import SynapseError from synapse.api.errors import SynapseError
from synapse.events import EventBase, relation_from_event from synapse.events import EventBase, relation_from_event
from synapse.logging.opentracing import trace
from synapse.storage.databases.main.relations import _RelatedEvent from synapse.storage.databases.main.relations import _RelatedEvent
from synapse.types import JsonDict, Requester, StreamToken, UserID from synapse.types import JsonDict, Requester, StreamToken, UserID
from synapse.visibility import filter_events_for_client from synapse.visibility import filter_events_for_client
@@ -364,6 +365,7 @@ class RelationsHandler:
return results return results
@trace
async def get_bundled_aggregations( async def get_bundled_aggregations(
self, events: Iterable[EventBase], user_id: str self, events: Iterable[EventBase], user_id: str
) -> Dict[str, BundledAggregations]: ) -> Dict[str, BundledAggregations]:

View File

@@ -778,7 +778,7 @@ class EventsPersistenceStorageController:
stale_forward_extremities_counter.observe(len(stale)) stale_forward_extremities_counter.observe(len(stale))
return result return result
async def _get_new_state_after_events( async def _get_new_state_after_events(
self, self,
room_id: str, room_id: str,

View File

@@ -29,6 +29,7 @@ from typing import (
from synapse.api.constants import EventTypes from synapse.api.constants import EventTypes
from synapse.events import EventBase from synapse.events import EventBase
from synapse.logging.opentracing import trace
from synapse.storage.state import StateFilter from synapse.storage.state import StateFilter
from synapse.storage.util.partial_state_events_tracker import ( from synapse.storage.util.partial_state_events_tracker import (
PartialCurrentStateTracker, PartialCurrentStateTracker,
@@ -175,6 +176,7 @@ class StateStorageController:
return self.stores.state._get_state_groups_from_groups(groups, state_filter) return self.stores.state._get_state_groups_from_groups(groups, state_filter)
@trace
async def get_state_for_events( async def get_state_for_events(
self, event_ids: Collection[str], state_filter: Optional[StateFilter] = None self, event_ids: Collection[str], state_filter: Optional[StateFilter] = None
) -> Dict[str, StateMap[EventBase]]: ) -> Dict[str, StateMap[EventBase]]:
@@ -221,6 +223,7 @@ class StateStorageController:
return {event: event_to_state[event] for event in event_ids} return {event: event_to_state[event] for event in event_ids}
@trace
async def get_state_ids_for_events( async def get_state_ids_for_events(
self, self,
event_ids: Collection[str], event_ids: Collection[str],
@@ -283,6 +286,7 @@ class StateStorageController:
) )
return state_map[event_id] return state_map[event_id]
@trace
async def get_state_ids_for_event( async def get_state_ids_for_event(
self, event_id: str, state_filter: Optional[StateFilter] = None self, event_id: str, state_filter: Optional[StateFilter] = None
) -> StateMap[str]: ) -> StateMap[str]:
@@ -323,6 +327,7 @@ class StateStorageController:
groups, state_filter or StateFilter.all() groups, state_filter or StateFilter.all()
) )
@trace
async def get_state_group_for_events( async def get_state_group_for_events(
self, self,
event_ids: Collection[str], event_ids: Collection[str],

View File

@@ -58,6 +58,7 @@ from twisted.internet import defer
from synapse.api.filtering import Filter from synapse.api.filtering import Filter
from synapse.events import EventBase from synapse.events import EventBase
from synapse.logging.context import make_deferred_yieldable, run_in_background from synapse.logging.context import make_deferred_yieldable, run_in_background
from synapse.logging.opentracing import trace
from synapse.storage._base import SQLBaseStore from synapse.storage._base import SQLBaseStore
from synapse.storage.database import ( from synapse.storage.database import (
DatabasePool, DatabasePool,
@@ -1346,6 +1347,7 @@ class StreamWorkerStore(EventsWorkerStore, SQLBaseStore):
return rows, next_token return rows, next_token
@trace
async def paginate_room_events( async def paginate_room_events(
self, self,
room_id: str, room_id: str,

View File

@@ -23,6 +23,7 @@ from synapse.api.constants import EventTypes, HistoryVisibility, Membership
from synapse.events import EventBase from synapse.events import EventBase
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
from synapse.events.utils import prune_event from synapse.events.utils import prune_event
from synapse.logging.opentracing import trace
from synapse.storage.controllers import StorageControllers from synapse.storage.controllers import StorageControllers
from synapse.storage.databases.main import DataStore from synapse.storage.databases.main import DataStore
from synapse.storage.state import StateFilter from synapse.storage.state import StateFilter
@@ -51,6 +52,7 @@ MEMBERSHIP_PRIORITY = (
_HISTORY_VIS_KEY: Final[Tuple[str, str]] = (EventTypes.RoomHistoryVisibility, "") _HISTORY_VIS_KEY: Final[Tuple[str, str]] = (EventTypes.RoomHistoryVisibility, "")
@trace
async def filter_events_for_client( async def filter_events_for_client(
storage: StorageControllers, storage: StorageControllers,
user_id: str, user_id: str,