mirror of
https://github.com/element-hq/synapse.git
synced 2024-11-25 02:55:46 +03:00
Add type hints to synapse/storage/databases/main/account_data.py
(#11546)
This commit is contained in:
parent
e5cdb9e233
commit
6da8591f2e
4 changed files with 87 additions and 33 deletions
1
changelog.d/11546.misc
Normal file
1
changelog.d/11546.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Add missing type hints to storage classes.
|
4
mypy.ini
4
mypy.ini
|
@ -25,7 +25,6 @@ exclude = (?x)
|
||||||
^(
|
^(
|
||||||
|synapse/storage/databases/__init__.py
|
|synapse/storage/databases/__init__.py
|
||||||
|synapse/storage/databases/main/__init__.py
|
|synapse/storage/databases/main/__init__.py
|
||||||
|synapse/storage/databases/main/account_data.py
|
|
||||||
|synapse/storage/databases/main/cache.py
|
|synapse/storage/databases/main/cache.py
|
||||||
|synapse/storage/databases/main/devices.py
|
|synapse/storage/databases/main/devices.py
|
||||||
|synapse/storage/databases/main/e2e_room_keys.py
|
|synapse/storage/databases/main/e2e_room_keys.py
|
||||||
|
@ -181,6 +180,9 @@ disallow_untyped_defs = True
|
||||||
[mypy-synapse.state.*]
|
[mypy-synapse.state.*]
|
||||||
disallow_untyped_defs = True
|
disallow_untyped_defs = True
|
||||||
|
|
||||||
|
[mypy-synapse.storage.databases.main.account_data]
|
||||||
|
disallow_untyped_defs = True
|
||||||
|
|
||||||
[mypy-synapse.storage.databases.main.client_ips]
|
[mypy-synapse.storage.databases.main.client_ips]
|
||||||
disallow_untyped_defs = True
|
disallow_untyped_defs = True
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,25 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Set, Tuple, cast
|
||||||
|
|
||||||
from synapse.api.constants import AccountDataTypes
|
from synapse.api.constants import AccountDataTypes
|
||||||
from synapse.replication.slave.storage._slaved_id_tracker import SlavedIdTracker
|
from synapse.replication.slave.storage._slaved_id_tracker import SlavedIdTracker
|
||||||
from synapse.replication.tcp.streams import AccountDataStream, TagAccountDataStream
|
from synapse.replication.tcp.streams import AccountDataStream, TagAccountDataStream
|
||||||
from synapse.storage._base import SQLBaseStore, db_to_json
|
from synapse.storage._base import db_to_json
|
||||||
from synapse.storage.database import DatabasePool
|
from synapse.storage.database import (
|
||||||
|
DatabasePool,
|
||||||
|
LoggingDatabaseConnection,
|
||||||
|
LoggingTransaction,
|
||||||
|
)
|
||||||
|
from synapse.storage.databases.main.cache import CacheInvalidationWorkerStore
|
||||||
from synapse.storage.engines import PostgresEngine
|
from synapse.storage.engines import PostgresEngine
|
||||||
from synapse.storage.util.id_generators import MultiWriterIdGenerator, StreamIdGenerator
|
from synapse.storage.util.id_generators import (
|
||||||
|
AbstractStreamIdGenerator,
|
||||||
|
AbstractStreamIdTracker,
|
||||||
|
MultiWriterIdGenerator,
|
||||||
|
StreamIdGenerator,
|
||||||
|
)
|
||||||
from synapse.types import JsonDict
|
from synapse.types import JsonDict
|
||||||
from synapse.util import json_encoder
|
from synapse.util import json_encoder
|
||||||
from synapse.util.caches.descriptors import cached
|
from synapse.util.caches.descriptors import cached
|
||||||
|
@ -34,13 +44,19 @@ if TYPE_CHECKING:
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AccountDataWorkerStore(SQLBaseStore):
|
class AccountDataWorkerStore(CacheInvalidationWorkerStore):
|
||||||
"""This is an abstract base class where subclasses must implement
|
def __init__(
|
||||||
`get_max_account_data_stream_id` which can be called in the initializer.
|
self,
|
||||||
"""
|
database: DatabasePool,
|
||||||
|
db_conn: LoggingDatabaseConnection,
|
||||||
|
hs: "HomeServer",
|
||||||
|
):
|
||||||
|
super().__init__(database, db_conn, hs)
|
||||||
|
|
||||||
def __init__(self, database: DatabasePool, db_conn, hs: "HomeServer"):
|
# `_can_write_to_account_data` indicates whether the current worker is allowed
|
||||||
self._instance_name = hs.get_instance_name()
|
# to write account data. A value of `True` implies that `_account_data_id_gen`
|
||||||
|
# is an `AbstractStreamIdGenerator` and not just a tracker.
|
||||||
|
self._account_data_id_gen: AbstractStreamIdTracker
|
||||||
|
|
||||||
if isinstance(database.engine, PostgresEngine):
|
if isinstance(database.engine, PostgresEngine):
|
||||||
self._can_write_to_account_data = (
|
self._can_write_to_account_data = (
|
||||||
|
@ -61,8 +77,6 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
writers=hs.config.worker.writers.account_data,
|
writers=hs.config.worker.writers.account_data,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self._can_write_to_account_data = True
|
|
||||||
|
|
||||||
# We shouldn't be running in worker mode with SQLite, but its useful
|
# We shouldn't be running in worker mode with SQLite, but its useful
|
||||||
# to support it for unit tests.
|
# to support it for unit tests.
|
||||||
#
|
#
|
||||||
|
@ -70,7 +84,8 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
# `StreamIdGenerator`, otherwise we use `SlavedIdTracker` which gets
|
# `StreamIdGenerator`, otherwise we use `SlavedIdTracker` which gets
|
||||||
# updated over replication. (Multiple writers are not supported for
|
# updated over replication. (Multiple writers are not supported for
|
||||||
# SQLite).
|
# SQLite).
|
||||||
if hs.get_instance_name() in hs.config.worker.writers.account_data:
|
if self._instance_name in hs.config.worker.writers.account_data:
|
||||||
|
self._can_write_to_account_data = True
|
||||||
self._account_data_id_gen = StreamIdGenerator(
|
self._account_data_id_gen = StreamIdGenerator(
|
||||||
db_conn,
|
db_conn,
|
||||||
"room_account_data",
|
"room_account_data",
|
||||||
|
@ -90,8 +105,6 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
"AccountDataAndTagsChangeCache", account_max
|
"AccountDataAndTagsChangeCache", account_max
|
||||||
)
|
)
|
||||||
|
|
||||||
super().__init__(database, db_conn, hs)
|
|
||||||
|
|
||||||
def get_max_account_data_stream_id(self) -> int:
|
def get_max_account_data_stream_id(self) -> int:
|
||||||
"""Get the current max stream ID for account data stream
|
"""Get the current max stream ID for account data stream
|
||||||
|
|
||||||
|
@ -113,7 +126,9 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
room_id string to per room account_data dicts.
|
room_id string to per room account_data dicts.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_account_data_for_user_txn(txn):
|
def get_account_data_for_user_txn(
|
||||||
|
txn: LoggingTransaction,
|
||||||
|
) -> Tuple[Dict[str, JsonDict], Dict[str, Dict[str, JsonDict]]]:
|
||||||
rows = self.db_pool.simple_select_list_txn(
|
rows = self.db_pool.simple_select_list_txn(
|
||||||
txn,
|
txn,
|
||||||
"account_data",
|
"account_data",
|
||||||
|
@ -132,7 +147,7 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
["room_id", "account_data_type", "content"],
|
["room_id", "account_data_type", "content"],
|
||||||
)
|
)
|
||||||
|
|
||||||
by_room = {}
|
by_room: Dict[str, Dict[str, JsonDict]] = {}
|
||||||
for row in rows:
|
for row in rows:
|
||||||
room_data = by_room.setdefault(row["room_id"], {})
|
room_data = by_room.setdefault(row["room_id"], {})
|
||||||
room_data[row["account_data_type"]] = db_to_json(row["content"])
|
room_data[row["account_data_type"]] = db_to_json(row["content"])
|
||||||
|
@ -177,7 +192,9 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
A dict of the room account_data
|
A dict of the room account_data
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_account_data_for_room_txn(txn):
|
def get_account_data_for_room_txn(
|
||||||
|
txn: LoggingTransaction,
|
||||||
|
) -> Dict[str, JsonDict]:
|
||||||
rows = self.db_pool.simple_select_list_txn(
|
rows = self.db_pool.simple_select_list_txn(
|
||||||
txn,
|
txn,
|
||||||
"room_account_data",
|
"room_account_data",
|
||||||
|
@ -207,7 +224,9 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
The room account_data for that type, or None if there isn't any set.
|
The room account_data for that type, or None if there isn't any set.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_account_data_for_room_and_type_txn(txn):
|
def get_account_data_for_room_and_type_txn(
|
||||||
|
txn: LoggingTransaction,
|
||||||
|
) -> Optional[JsonDict]:
|
||||||
content_json = self.db_pool.simple_select_one_onecol_txn(
|
content_json = self.db_pool.simple_select_one_onecol_txn(
|
||||||
txn,
|
txn,
|
||||||
table="room_account_data",
|
table="room_account_data",
|
||||||
|
@ -243,14 +262,16 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
if last_id == current_id:
|
if last_id == current_id:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_updated_global_account_data_txn(txn):
|
def get_updated_global_account_data_txn(
|
||||||
|
txn: LoggingTransaction,
|
||||||
|
) -> List[Tuple[int, str, str]]:
|
||||||
sql = (
|
sql = (
|
||||||
"SELECT stream_id, user_id, account_data_type"
|
"SELECT stream_id, user_id, account_data_type"
|
||||||
" FROM account_data WHERE ? < stream_id AND stream_id <= ?"
|
" FROM account_data WHERE ? < stream_id AND stream_id <= ?"
|
||||||
" ORDER BY stream_id ASC LIMIT ?"
|
" ORDER BY stream_id ASC LIMIT ?"
|
||||||
)
|
)
|
||||||
txn.execute(sql, (last_id, current_id, limit))
|
txn.execute(sql, (last_id, current_id, limit))
|
||||||
return txn.fetchall()
|
return cast(List[Tuple[int, str, str]], txn.fetchall())
|
||||||
|
|
||||||
return await self.db_pool.runInteraction(
|
return await self.db_pool.runInteraction(
|
||||||
"get_updated_global_account_data", get_updated_global_account_data_txn
|
"get_updated_global_account_data", get_updated_global_account_data_txn
|
||||||
|
@ -273,14 +294,16 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
if last_id == current_id:
|
if last_id == current_id:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_updated_room_account_data_txn(txn):
|
def get_updated_room_account_data_txn(
|
||||||
|
txn: LoggingTransaction,
|
||||||
|
) -> List[Tuple[int, str, str, str]]:
|
||||||
sql = (
|
sql = (
|
||||||
"SELECT stream_id, user_id, room_id, account_data_type"
|
"SELECT stream_id, user_id, room_id, account_data_type"
|
||||||
" FROM room_account_data WHERE ? < stream_id AND stream_id <= ?"
|
" FROM room_account_data WHERE ? < stream_id AND stream_id <= ?"
|
||||||
" ORDER BY stream_id ASC LIMIT ?"
|
" ORDER BY stream_id ASC LIMIT ?"
|
||||||
)
|
)
|
||||||
txn.execute(sql, (last_id, current_id, limit))
|
txn.execute(sql, (last_id, current_id, limit))
|
||||||
return txn.fetchall()
|
return cast(List[Tuple[int, str, str, str]], txn.fetchall())
|
||||||
|
|
||||||
return await self.db_pool.runInteraction(
|
return await self.db_pool.runInteraction(
|
||||||
"get_updated_room_account_data", get_updated_room_account_data_txn
|
"get_updated_room_account_data", get_updated_room_account_data_txn
|
||||||
|
@ -299,7 +322,9 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
mapping from room_id string to per room account_data dicts.
|
mapping from room_id string to per room account_data dicts.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_updated_account_data_for_user_txn(txn):
|
def get_updated_account_data_for_user_txn(
|
||||||
|
txn: LoggingTransaction,
|
||||||
|
) -> Tuple[Dict[str, JsonDict], Dict[str, Dict[str, JsonDict]]]:
|
||||||
sql = (
|
sql = (
|
||||||
"SELECT account_data_type, content FROM account_data"
|
"SELECT account_data_type, content FROM account_data"
|
||||||
" WHERE user_id = ? AND stream_id > ?"
|
" WHERE user_id = ? AND stream_id > ?"
|
||||||
|
@ -316,7 +341,7 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
|
|
||||||
txn.execute(sql, (user_id, stream_id))
|
txn.execute(sql, (user_id, stream_id))
|
||||||
|
|
||||||
account_data_by_room = {}
|
account_data_by_room: Dict[str, Dict[str, JsonDict]] = {}
|
||||||
for row in txn:
|
for row in txn:
|
||||||
room_account_data = account_data_by_room.setdefault(row[0], {})
|
room_account_data = account_data_by_room.setdefault(row[0], {})
|
||||||
room_account_data[row[1]] = db_to_json(row[2])
|
room_account_data[row[1]] = db_to_json(row[2])
|
||||||
|
@ -353,12 +378,15 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_replication_rows(self, stream_name, instance_name, token, rows):
|
def process_replication_rows(
|
||||||
|
self,
|
||||||
|
stream_name: str,
|
||||||
|
instance_name: str,
|
||||||
|
token: int,
|
||||||
|
rows: Iterable[Any],
|
||||||
|
) -> None:
|
||||||
if stream_name == TagAccountDataStream.NAME:
|
if stream_name == TagAccountDataStream.NAME:
|
||||||
self._account_data_id_gen.advance(instance_name, token)
|
self._account_data_id_gen.advance(instance_name, token)
|
||||||
for row in rows:
|
|
||||||
self.get_tags_for_user.invalidate((row.user_id,))
|
|
||||||
self._account_data_stream_cache.entity_has_changed(row.user_id, token)
|
|
||||||
elif stream_name == AccountDataStream.NAME:
|
elif stream_name == AccountDataStream.NAME:
|
||||||
self._account_data_id_gen.advance(instance_name, token)
|
self._account_data_id_gen.advance(instance_name, token)
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
@ -372,7 +400,8 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
(row.user_id, row.room_id, row.data_type)
|
(row.user_id, row.room_id, row.data_type)
|
||||||
)
|
)
|
||||||
self._account_data_stream_cache.entity_has_changed(row.user_id, token)
|
self._account_data_stream_cache.entity_has_changed(row.user_id, token)
|
||||||
return super().process_replication_rows(stream_name, instance_name, token, rows)
|
|
||||||
|
super().process_replication_rows(stream_name, instance_name, token, rows)
|
||||||
|
|
||||||
async def add_account_data_to_room(
|
async def add_account_data_to_room(
|
||||||
self, user_id: str, room_id: str, account_data_type: str, content: JsonDict
|
self, user_id: str, room_id: str, account_data_type: str, content: JsonDict
|
||||||
|
@ -389,6 +418,7 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
The maximum stream ID.
|
The maximum stream ID.
|
||||||
"""
|
"""
|
||||||
assert self._can_write_to_account_data
|
assert self._can_write_to_account_data
|
||||||
|
assert isinstance(self._account_data_id_gen, AbstractStreamIdGenerator)
|
||||||
|
|
||||||
content_json = json_encoder.encode(content)
|
content_json = json_encoder.encode(content)
|
||||||
|
|
||||||
|
@ -431,6 +461,7 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
The maximum stream ID.
|
The maximum stream ID.
|
||||||
"""
|
"""
|
||||||
assert self._can_write_to_account_data
|
assert self._can_write_to_account_data
|
||||||
|
assert isinstance(self._account_data_id_gen, AbstractStreamIdGenerator)
|
||||||
|
|
||||||
async with self._account_data_id_gen.get_next() as next_id:
|
async with self._account_data_id_gen.get_next() as next_id:
|
||||||
await self.db_pool.runInteraction(
|
await self.db_pool.runInteraction(
|
||||||
|
@ -452,7 +483,7 @@ class AccountDataWorkerStore(SQLBaseStore):
|
||||||
|
|
||||||
def _add_account_data_for_user(
|
def _add_account_data_for_user(
|
||||||
self,
|
self,
|
||||||
txn,
|
txn: LoggingTransaction,
|
||||||
next_id: int,
|
next_id: int,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
account_data_type: str,
|
account_data_type: str,
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, List, Tuple, cast
|
from typing import Any, Dict, Iterable, List, Tuple, cast
|
||||||
|
|
||||||
|
from synapse.replication.tcp.streams import TagAccountDataStream
|
||||||
from synapse.storage._base import db_to_json
|
from synapse.storage._base import db_to_json
|
||||||
from synapse.storage.database import LoggingTransaction
|
from synapse.storage.database import LoggingTransaction
|
||||||
from synapse.storage.databases.main.account_data import AccountDataWorkerStore
|
from synapse.storage.databases.main.account_data import AccountDataWorkerStore
|
||||||
|
from synapse.storage.util.id_generators import AbstractStreamIdGenerator
|
||||||
from synapse.types import JsonDict
|
from synapse.types import JsonDict
|
||||||
from synapse.util import json_encoder
|
from synapse.util import json_encoder
|
||||||
from synapse.util.caches.descriptors import cached
|
from synapse.util.caches.descriptors import cached
|
||||||
|
@ -204,6 +206,7 @@ class TagsWorkerStore(AccountDataWorkerStore):
|
||||||
The next account data ID.
|
The next account data ID.
|
||||||
"""
|
"""
|
||||||
assert self._can_write_to_account_data
|
assert self._can_write_to_account_data
|
||||||
|
assert isinstance(self._account_data_id_gen, AbstractStreamIdGenerator)
|
||||||
|
|
||||||
content_json = json_encoder.encode(content)
|
content_json = json_encoder.encode(content)
|
||||||
|
|
||||||
|
@ -230,6 +233,7 @@ class TagsWorkerStore(AccountDataWorkerStore):
|
||||||
The next account data ID.
|
The next account data ID.
|
||||||
"""
|
"""
|
||||||
assert self._can_write_to_account_data
|
assert self._can_write_to_account_data
|
||||||
|
assert isinstance(self._account_data_id_gen, AbstractStreamIdGenerator)
|
||||||
|
|
||||||
def remove_tag_txn(txn: LoggingTransaction, next_id: int) -> None:
|
def remove_tag_txn(txn: LoggingTransaction, next_id: int) -> None:
|
||||||
sql = (
|
sql = (
|
||||||
|
@ -258,6 +262,7 @@ class TagsWorkerStore(AccountDataWorkerStore):
|
||||||
next_id: The the revision to advance to.
|
next_id: The the revision to advance to.
|
||||||
"""
|
"""
|
||||||
assert self._can_write_to_account_data
|
assert self._can_write_to_account_data
|
||||||
|
assert isinstance(self._account_data_id_gen, AbstractStreamIdGenerator)
|
||||||
|
|
||||||
txn.call_after(
|
txn.call_after(
|
||||||
self._account_data_stream_cache.entity_has_changed, user_id, next_id
|
self._account_data_stream_cache.entity_has_changed, user_id, next_id
|
||||||
|
@ -287,6 +292,21 @@ class TagsWorkerStore(AccountDataWorkerStore):
|
||||||
# than the id that the client has.
|
# than the id that the client has.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def process_replication_rows(
|
||||||
|
self,
|
||||||
|
stream_name: str,
|
||||||
|
instance_name: str,
|
||||||
|
token: int,
|
||||||
|
rows: Iterable[Any],
|
||||||
|
) -> None:
|
||||||
|
if stream_name == TagAccountDataStream.NAME:
|
||||||
|
self._account_data_id_gen.advance(instance_name, token)
|
||||||
|
for row in rows:
|
||||||
|
self.get_tags_for_user.invalidate((row.user_id,))
|
||||||
|
self._account_data_stream_cache.entity_has_changed(row.user_id, token)
|
||||||
|
|
||||||
|
super().process_replication_rows(stream_name, instance_name, token, rows)
|
||||||
|
|
||||||
|
|
||||||
class TagsStore(TagsWorkerStore):
|
class TagsStore(TagsWorkerStore):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in a new issue