Add conn_id field

This commit is contained in:
Erik Johnston 2024-07-17 13:54:00 +01:00
parent d44f7e12b1
commit 53273db3e8
4 changed files with 36 additions and 5 deletions

View file

@ -1807,7 +1807,7 @@ class SlidingSyncHandler:
"""
user_id = sync_config.user.to_string()
device_id = sync_config.device_id
device_id = sync_config.requester.device_id
# Check that this request has a valid device ID (not all requests have
# to belong to a device, and so device_id is None), and that the

View file

@ -881,7 +881,6 @@ class SlidingSyncRestServlet(RestServlet):
)
user = requester.user
device_id = requester.device_id
timeout = parse_integer(request, "timeout", default=0)
# Position in the stream
@ -902,11 +901,12 @@ class SlidingSyncRestServlet(RestServlet):
sync_config = SlidingSyncConfig(
user=user,
device_id=device_id,
requester=requester,
# FIXME: Currently, we're just manually copying the fields from the
# `SlidingSyncBody` into the config. How can we gurantee into the future
# `SlidingSyncBody` into the config. How can we guarantee into the future
# that we don't forget any? I would like something more structured like
# `copy_attributes(from=body, to=config)`
conn_id=body.conn_id,
lists=body.lists,
room_subscriptions=body.room_subscriptions,
extensions=body.extensions,

View file

@ -34,6 +34,7 @@ from synapse.events import EventBase
from synapse.types import (
JsonDict,
JsonMapping,
Requester,
SlidingSyncStreamToken,
StreamToken,
UserID,
@ -108,7 +109,7 @@ class SlidingSyncConfig(SlidingSyncBody):
"""
user: UserID
device_id: Optional[str]
requester: Requester
# Pydantic config
class Config:
@ -119,6 +120,31 @@ class SlidingSyncConfig(SlidingSyncBody):
# Allow custom types like `UserID` to be used in the model
arbitrary_types_allowed = True
def connection_id(self) -> str:
"""Return a string identifier for this connection. May clash with
connection IDs from different users.
This is generally a combination of device ID and conn_id. However, both
these two are optional (e.g. puppet access tokens don't have device
IDs), so this handles those edge cases.
"""
# `conn_id` can be null, in which case we default to the empty string
# (if conn ID is empty then the client can't have multiple sync loops)
conn_id = self.conn_id or ""
if self.requester.device_id:
return f"D/{self.requester.device_id}/{conn_id}"
if self.requester.access_token_id:
# If we don't have a device, then the access token ID should be a
# stable ID.
return f"A/{self.requester.access_token_id}/{conn_id}"
# If we have neither then its likely an AS or some weird token. Either
# way we can just fail here.
raise Exception("Cannot use sliding sync with access token type")
class OperationType(Enum):
"""

View file

@ -120,6 +120,9 @@ class SlidingSyncBody(RequestBodyModel):
Sliding Sync API request body.
Attributes:
conn_id: An optional string to identify this connection to the server. If this
is missing, only 1 sliding sync connection can be made to the server at
any one time.
lists: Sliding window API. A map of list key to list information
(:class:`SlidingSyncList`). Max lists: 100. The list keys should be
arbitrary strings which the client is using to refer to the list. Keep this
@ -315,6 +318,8 @@ class SlidingSyncBody(RequestBodyModel):
to_device: Optional[ToDeviceExtension] = None
conn_id: Optional[str]
# mypy workaround via https://github.com/pydantic/pydantic/issues/156#issuecomment-1130883884
if TYPE_CHECKING:
lists: Optional[Dict[str, SlidingSyncList]] = None