mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-02 10:46:06 -04:00
Make token serializing/deserializing async (#8427)
The idea is that in future tokens will encode a mapping of instance to position. However, we don't want to include the full instance name in the string representation, so instead we'll have a mapping between instance name and an immutable integer ID in the DB that we can use instead. We'll then do the lookup when we serialize/deserialize the token (we could alternatively pass around an `Instance` type that includes both the name and ID, but that turns out to be a lot more invasive).
This commit is contained in:
parent
a0a1ba6973
commit
7941372ec8
17 changed files with 115 additions and 59 deletions
|
@ -18,7 +18,17 @@ import re
|
|||
import string
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from typing import Any, Dict, Mapping, MutableMapping, Optional, Tuple, Type, TypeVar
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Dict,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
)
|
||||
|
||||
import attr
|
||||
from signedjson.key import decode_verify_key_bytes
|
||||
|
@ -26,6 +36,9 @@ from unpaddedbase64 import decode_base64
|
|||
|
||||
from synapse.api.errors import Codes, SynapseError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from synapse.storage.databases.main import DataStore
|
||||
|
||||
# define a version of typing.Collection that works on python 3.5
|
||||
if sys.version_info[:3] >= (3, 6, 0):
|
||||
from typing import Collection
|
||||
|
@ -393,7 +406,7 @@ class RoomStreamToken:
|
|||
stream = attr.ib(type=int, validator=attr.validators.instance_of(int))
|
||||
|
||||
@classmethod
|
||||
def parse(cls, string: str) -> "RoomStreamToken":
|
||||
async def parse(cls, store: "DataStore", string: str) -> "RoomStreamToken":
|
||||
try:
|
||||
if string[0] == "s":
|
||||
return cls(topological=None, stream=int(string[1:]))
|
||||
|
@ -428,7 +441,7 @@ class RoomStreamToken:
|
|||
def as_tuple(self) -> Tuple[Optional[int], int]:
|
||||
return (self.topological, self.stream)
|
||||
|
||||
def __str__(self) -> str:
|
||||
async def to_string(self, store: "DataStore") -> str:
|
||||
if self.topological is not None:
|
||||
return "t%d-%d" % (self.topological, self.stream)
|
||||
else:
|
||||
|
@ -453,18 +466,32 @@ class StreamToken:
|
|||
START = None # type: StreamToken
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, string):
|
||||
async def from_string(cls, store: "DataStore", string: str) -> "StreamToken":
|
||||
try:
|
||||
keys = string.split(cls._SEPARATOR)
|
||||
while len(keys) < len(attr.fields(cls)):
|
||||
# i.e. old token from before receipt_key
|
||||
keys.append("0")
|
||||
return cls(RoomStreamToken.parse(keys[0]), *(int(k) for k in keys[1:]))
|
||||
return cls(
|
||||
await RoomStreamToken.parse(store, keys[0]), *(int(k) for k in keys[1:])
|
||||
)
|
||||
except Exception:
|
||||
raise SynapseError(400, "Invalid Token")
|
||||
|
||||
def to_string(self):
|
||||
return self._SEPARATOR.join([str(k) for k in attr.astuple(self, recurse=False)])
|
||||
async def to_string(self, store: "DataStore") -> str:
|
||||
return self._SEPARATOR.join(
|
||||
[
|
||||
await self.room_key.to_string(store),
|
||||
str(self.presence_key),
|
||||
str(self.typing_key),
|
||||
str(self.receipt_key),
|
||||
str(self.account_data_key),
|
||||
str(self.push_rules_key),
|
||||
str(self.to_device_key),
|
||||
str(self.device_list_key),
|
||||
str(self.groups_key),
|
||||
]
|
||||
)
|
||||
|
||||
@property
|
||||
def room_stream_id(self):
|
||||
|
@ -493,7 +520,7 @@ class StreamToken:
|
|||
return attr.evolve(self, **{key: new_value})
|
||||
|
||||
|
||||
StreamToken.START = StreamToken.from_string("s0_0")
|
||||
StreamToken.START = StreamToken(RoomStreamToken(None, 0), 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
|
||||
|
||||
@attr.s(slots=True, frozen=True)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue