matrix-synapse 1.139.2__cp39-abi3-manylinux_2_28_aarch64.whl → 1.140.0rc1__cp39-abi3-manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of matrix-synapse might be problematic. Click here for more details.
- {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/METADATA +5 -3
- {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/RECORD +157 -154
- synapse/_scripts/generate_workers_map.py +6 -1
- synapse/_scripts/synapse_port_db.py +0 -2
- synapse/_scripts/update_synapse_database.py +1 -6
- synapse/api/auth/base.py +1 -3
- synapse/api/auth/mas.py +6 -8
- synapse/api/auth/msc3861_delegated.py +6 -8
- synapse/api/errors.py +3 -0
- synapse/app/_base.py +101 -39
- synapse/app/admin_cmd.py +2 -4
- synapse/app/appservice.py +1 -1
- synapse/app/client_reader.py +1 -1
- synapse/app/event_creator.py +1 -1
- synapse/app/federation_reader.py +1 -1
- synapse/app/federation_sender.py +1 -1
- synapse/app/frontend_proxy.py +1 -1
- synapse/app/generic_worker.py +17 -11
- synapse/app/homeserver.py +85 -47
- synapse/app/media_repository.py +1 -1
- synapse/app/phone_stats_home.py +16 -14
- synapse/app/pusher.py +1 -1
- synapse/app/synchrotron.py +1 -1
- synapse/app/user_dir.py +1 -1
- synapse/appservice/__init__.py +29 -2
- synapse/appservice/scheduler.py +8 -8
- synapse/config/_base.py +32 -14
- synapse/config/_base.pyi +5 -3
- synapse/config/experimental.py +3 -0
- synapse/config/homeserver.py +27 -1
- synapse/config/logger.py +3 -4
- synapse/config/matrixrtc.py +67 -0
- synapse/crypto/keyring.py +18 -4
- synapse/events/auto_accept_invites.py +0 -1
- synapse/federation/federation_client.py +39 -0
- synapse/federation/federation_server.py +1 -1
- synapse/federation/send_queue.py +3 -0
- synapse/federation/sender/__init__.py +24 -8
- synapse/federation/sender/per_destination_queue.py +31 -8
- synapse/federation/sender/transaction_manager.py +12 -0
- synapse/federation/transport/client.py +29 -0
- synapse/handlers/account_validity.py +2 -4
- synapse/handlers/appservice.py +5 -7
- synapse/handlers/deactivate_account.py +2 -3
- synapse/handlers/delayed_events.py +10 -13
- synapse/handlers/device.py +14 -14
- synapse/handlers/e2e_keys.py +4 -3
- synapse/handlers/federation.py +7 -11
- synapse/handlers/federation_event.py +5 -6
- synapse/handlers/message.py +16 -10
- synapse/handlers/pagination.py +3 -7
- synapse/handlers/presence.py +21 -25
- synapse/handlers/profile.py +1 -1
- synapse/handlers/read_marker.py +3 -1
- synapse/handlers/register.py +8 -1
- synapse/handlers/room.py +13 -4
- synapse/handlers/room_member.py +11 -7
- synapse/handlers/room_policy.py +96 -2
- synapse/handlers/sso.py +1 -1
- synapse/handlers/stats.py +5 -3
- synapse/handlers/sync.py +20 -13
- synapse/handlers/typing.py +5 -10
- synapse/handlers/user_directory.py +12 -11
- synapse/handlers/worker_lock.py +19 -15
- synapse/http/client.py +18 -13
- synapse/http/federation/matrix_federation_agent.py +6 -1
- synapse/http/federation/well_known_resolver.py +3 -1
- synapse/http/matrixfederationclient.py +50 -11
- synapse/http/proxy.py +2 -2
- synapse/http/server.py +36 -2
- synapse/http/site.py +109 -17
- synapse/logging/context.py +165 -63
- synapse/logging/opentracing.py +30 -6
- synapse/logging/scopecontextmanager.py +161 -0
- synapse/media/_base.py +2 -1
- synapse/media/media_repository.py +20 -6
- synapse/media/url_previewer.py +5 -6
- synapse/metrics/_gc.py +3 -1
- synapse/metrics/background_process_metrics.py +128 -24
- synapse/metrics/common_usage_metrics.py +3 -5
- synapse/module_api/__init__.py +42 -5
- synapse/notifier.py +10 -3
- synapse/push/emailpusher.py +5 -4
- synapse/push/httppusher.py +6 -6
- synapse/push/pusherpool.py +3 -8
- synapse/replication/http/devices.py +0 -41
- synapse/replication/tcp/client.py +8 -5
- synapse/replication/tcp/handler.py +2 -3
- synapse/replication/tcp/protocol.py +14 -7
- synapse/replication/tcp/redis.py +16 -11
- synapse/replication/tcp/resource.py +5 -4
- synapse/replication/tcp/streams/__init__.py +2 -0
- synapse/res/providers.json +6 -5
- synapse/rest/__init__.py +2 -0
- synapse/rest/admin/__init__.py +4 -0
- synapse/rest/admin/events.py +69 -0
- synapse/rest/admin/media.py +70 -2
- synapse/rest/client/matrixrtc.py +52 -0
- synapse/rest/client/push_rule.py +1 -1
- synapse/rest/client/room.py +2 -3
- synapse/rest/client/sync.py +1 -0
- synapse/rest/client/transactions.py +1 -1
- synapse/server.py +271 -38
- synapse/server_notices/server_notices_manager.py +1 -0
- synapse/state/__init__.py +4 -1
- synapse/storage/_base.py +1 -1
- synapse/storage/background_updates.py +8 -3
- synapse/storage/controllers/persist_events.py +4 -3
- synapse/storage/controllers/purge_events.py +2 -3
- synapse/storage/controllers/state.py +5 -5
- synapse/storage/database.py +12 -7
- synapse/storage/databases/main/__init__.py +7 -2
- synapse/storage/databases/main/cache.py +4 -3
- synapse/storage/databases/main/censor_events.py +1 -1
- synapse/storage/databases/main/client_ips.py +9 -8
- synapse/storage/databases/main/deviceinbox.py +7 -6
- synapse/storage/databases/main/devices.py +4 -4
- synapse/storage/databases/main/end_to_end_keys.py +6 -3
- synapse/storage/databases/main/event_federation.py +7 -6
- synapse/storage/databases/main/event_push_actions.py +13 -13
- synapse/storage/databases/main/events_bg_updates.py +1 -1
- synapse/storage/databases/main/events_worker.py +6 -8
- synapse/storage/databases/main/lock.py +17 -13
- synapse/storage/databases/main/media_repository.py +2 -2
- synapse/storage/databases/main/metrics.py +6 -6
- synapse/storage/databases/main/monthly_active_users.py +3 -4
- synapse/storage/databases/main/receipts.py +1 -1
- synapse/storage/databases/main/registration.py +18 -19
- synapse/storage/databases/main/roommember.py +1 -1
- synapse/storage/databases/main/session.py +3 -3
- synapse/storage/databases/main/sliding_sync.py +2 -2
- synapse/storage/databases/main/transactions.py +3 -3
- synapse/storage/databases/state/store.py +2 -0
- synapse/synapse_rust/http_client.pyi +4 -0
- synapse/synapse_rust.abi3.so +0 -0
- synapse/util/async_helpers.py +36 -24
- synapse/util/batching_queue.py +16 -6
- synapse/util/caches/__init__.py +1 -1
- synapse/util/caches/deferred_cache.py +4 -0
- synapse/util/caches/descriptors.py +14 -2
- synapse/util/caches/dictionary_cache.py +6 -1
- synapse/util/caches/expiringcache.py +16 -5
- synapse/util/caches/lrucache.py +14 -26
- synapse/util/caches/response_cache.py +11 -1
- synapse/util/clock.py +215 -39
- synapse/util/constants.py +2 -0
- synapse/util/daemonize.py +5 -1
- synapse/util/distributor.py +9 -5
- synapse/util/metrics.py +35 -6
- synapse/util/ratelimitutils.py +4 -1
- synapse/util/retryutils.py +7 -4
- synapse/util/task_scheduler.py +11 -14
- synapse/logging/filter.py +0 -38
- {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/AUTHORS.rst +0 -0
- {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/LICENSE-AGPL-3.0 +0 -0
- {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/LICENSE-COMMERCIAL +0 -0
- {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/WHEEL +0 -0
- {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/entry_points.txt +0 -0
synapse/handlers/room_policy.py
CHANGED
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
import logging
|
|
18
18
|
from typing import TYPE_CHECKING
|
|
19
19
|
|
|
20
|
+
from signedjson.key import decode_verify_key_bytes
|
|
21
|
+
from unpaddedbase64 import decode_base64
|
|
22
|
+
|
|
23
|
+
from synapse.api.errors import SynapseError
|
|
24
|
+
from synapse.crypto.keyring import VerifyJsonRequest
|
|
20
25
|
from synapse.events import EventBase
|
|
21
26
|
from synapse.types.handlers.policy_server import RECOMMENDATION_OK
|
|
22
27
|
from synapse.util.stringutils import parse_and_validate_server_name
|
|
@@ -26,6 +31,9 @@ if TYPE_CHECKING:
|
|
|
26
31
|
|
|
27
32
|
logger = logging.getLogger(__name__)
|
|
28
33
|
|
|
34
|
+
POLICY_SERVER_EVENT_TYPE = "org.matrix.msc4284.policy"
|
|
35
|
+
POLICY_SERVER_KEY_ID = "ed25519:policy_server"
|
|
36
|
+
|
|
29
37
|
|
|
30
38
|
class RoomPolicyHandler:
|
|
31
39
|
def __init__(self, hs: "HomeServer"):
|
|
@@ -54,11 +62,11 @@ class RoomPolicyHandler:
|
|
|
54
62
|
Returns:
|
|
55
63
|
bool: True if the event is allowed in the room, False otherwise.
|
|
56
64
|
"""
|
|
57
|
-
if event.type ==
|
|
65
|
+
if event.type == POLICY_SERVER_EVENT_TYPE and event.state_key is not None:
|
|
58
66
|
return True # always allow policy server change events
|
|
59
67
|
|
|
60
68
|
policy_event = await self._storage_controllers.state.get_current_state_event(
|
|
61
|
-
event.room_id,
|
|
69
|
+
event.room_id, POLICY_SERVER_EVENT_TYPE, ""
|
|
62
70
|
)
|
|
63
71
|
if not policy_event:
|
|
64
72
|
return True # no policy server == default allow
|
|
@@ -81,6 +89,22 @@ class RoomPolicyHandler:
|
|
|
81
89
|
if not is_in_room:
|
|
82
90
|
return True # policy server not in room == default allow
|
|
83
91
|
|
|
92
|
+
# Check if the event has been signed with the public key in the policy server state event.
|
|
93
|
+
# If it is, we can save an HTTP hit.
|
|
94
|
+
# We actually want to get the policy server state event BEFORE THE EVENT rather than
|
|
95
|
+
# the current state value, else changing the public key will cause all of these checks to fail.
|
|
96
|
+
# However, if we are checking outlier events (which we will due to is_event_allowed being called
|
|
97
|
+
# near the edges at _check_sigs_and_hash) we won't know the state before the event, so the
|
|
98
|
+
# only safe option is to use the current state
|
|
99
|
+
public_key = policy_event.content.get("public_key", None)
|
|
100
|
+
if public_key is not None and isinstance(public_key, str):
|
|
101
|
+
valid = await self._verify_policy_server_signature(
|
|
102
|
+
event, policy_server, public_key
|
|
103
|
+
)
|
|
104
|
+
if valid:
|
|
105
|
+
return True
|
|
106
|
+
# fallthrough to hit /check manually
|
|
107
|
+
|
|
84
108
|
# At this point, the server appears valid and is in the room, so ask it to check
|
|
85
109
|
# the event.
|
|
86
110
|
recommendation = await self._federation_client.get_pdu_policy_recommendation(
|
|
@@ -90,3 +114,73 @@ class RoomPolicyHandler:
|
|
|
90
114
|
return False
|
|
91
115
|
|
|
92
116
|
return True # default allow
|
|
117
|
+
|
|
118
|
+
async def _verify_policy_server_signature(
|
|
119
|
+
self, event: EventBase, policy_server: str, public_key: str
|
|
120
|
+
) -> bool:
|
|
121
|
+
# check the event is signed with this (via, public_key).
|
|
122
|
+
verify_json_req = VerifyJsonRequest.from_event(policy_server, event, 0)
|
|
123
|
+
try:
|
|
124
|
+
key_bytes = decode_base64(public_key)
|
|
125
|
+
verify_key = decode_verify_key_bytes(POLICY_SERVER_KEY_ID, key_bytes)
|
|
126
|
+
# We would normally use KeyRing.verify_event_for_server but we can't here as we don't
|
|
127
|
+
# want to fetch the server key, and instead want to use the public key in the state event.
|
|
128
|
+
await self._hs.get_keyring().process_json(verify_key, verify_json_req)
|
|
129
|
+
# if the event is correctly signed by the public key in the policy server state event = Allow
|
|
130
|
+
return True
|
|
131
|
+
except Exception as ex:
|
|
132
|
+
logger.warning(
|
|
133
|
+
"failed to verify event using public key in policy server event: %s", ex
|
|
134
|
+
)
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
async def ask_policy_server_to_sign_event(
|
|
138
|
+
self, event: EventBase, verify: bool = False
|
|
139
|
+
) -> None:
|
|
140
|
+
"""Ask the policy server to sign this event. The signature is added to the event signatures block.
|
|
141
|
+
|
|
142
|
+
Does nothing if there is no policy server state event in the room. If the policy server
|
|
143
|
+
refuses to sign the event (as it's marked as spam) does nothing.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
event: The event to sign
|
|
147
|
+
verify: If True, verify that the signature is correctly signed by the public_key in the
|
|
148
|
+
policy server state event.
|
|
149
|
+
Raises:
|
|
150
|
+
if verify=True and the policy server signed the event with an invalid signature. Does
|
|
151
|
+
not raise if the policy server refuses to sign the event.
|
|
152
|
+
"""
|
|
153
|
+
policy_event = await self._storage_controllers.state.get_current_state_event(
|
|
154
|
+
event.room_id, POLICY_SERVER_EVENT_TYPE, ""
|
|
155
|
+
)
|
|
156
|
+
if not policy_event:
|
|
157
|
+
return
|
|
158
|
+
policy_server = policy_event.content.get("via", None)
|
|
159
|
+
if policy_server is None or not isinstance(policy_server, str):
|
|
160
|
+
return
|
|
161
|
+
# Only ask to sign events if the policy state event has a public_key (so they can be subsequently verified)
|
|
162
|
+
public_key = policy_event.content.get("public_key", None)
|
|
163
|
+
if public_key is None or not isinstance(public_key, str):
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
# Ask the policy server to sign this event.
|
|
167
|
+
# We set a smallish timeout here as we don't want to block event sending too long.
|
|
168
|
+
signature = await self._federation_client.ask_policy_server_to_sign_event(
|
|
169
|
+
policy_server,
|
|
170
|
+
event,
|
|
171
|
+
timeout=3000,
|
|
172
|
+
)
|
|
173
|
+
if (
|
|
174
|
+
# the policy server returns {} if it refuses to sign the event.
|
|
175
|
+
signature and len(signature) > 0
|
|
176
|
+
):
|
|
177
|
+
event.signatures.update(signature)
|
|
178
|
+
if verify:
|
|
179
|
+
is_valid = await self._verify_policy_server_signature(
|
|
180
|
+
event, policy_server, public_key
|
|
181
|
+
)
|
|
182
|
+
if not is_valid:
|
|
183
|
+
raise SynapseError(
|
|
184
|
+
500,
|
|
185
|
+
f"policy server {policy_server} failed to sign event correctly",
|
|
186
|
+
)
|
synapse/handlers/sso.py
CHANGED
|
@@ -224,7 +224,7 @@ class SsoHandler:
|
|
|
224
224
|
)
|
|
225
225
|
|
|
226
226
|
# a lock on the mappings
|
|
227
|
-
self._mapping_lock = Linearizer(
|
|
227
|
+
self._mapping_lock = Linearizer(clock=hs.get_clock(), name="sso_user_mapping")
|
|
228
228
|
|
|
229
229
|
# a map from session id to session data
|
|
230
230
|
self._username_mapping_sessions: Dict[str, UsernameMappingSession] = {}
|
synapse/handlers/stats.py
CHANGED
|
@@ -33,7 +33,6 @@ from typing import (
|
|
|
33
33
|
|
|
34
34
|
from synapse.api.constants import EventContentFields, EventTypes, Membership
|
|
35
35
|
from synapse.metrics import SERVER_NAME_LABEL, event_processing_positions
|
|
36
|
-
from synapse.metrics.background_process_metrics import run_as_background_process
|
|
37
36
|
from synapse.storage.databases.main.state_deltas import StateDelta
|
|
38
37
|
from synapse.types import JsonDict
|
|
39
38
|
from synapse.util.events import get_plain_text_topic_from_event_content
|
|
@@ -75,7 +74,10 @@ class StatsHandler:
|
|
|
75
74
|
|
|
76
75
|
# We kick this off so that we don't have to wait for a change before
|
|
77
76
|
# we start populating stats
|
|
78
|
-
self.clock.call_later(
|
|
77
|
+
self.clock.call_later(
|
|
78
|
+
0,
|
|
79
|
+
self.notify_new_event,
|
|
80
|
+
)
|
|
79
81
|
|
|
80
82
|
def notify_new_event(self) -> None:
|
|
81
83
|
"""Called when there may be more deltas to process"""
|
|
@@ -90,7 +92,7 @@ class StatsHandler:
|
|
|
90
92
|
finally:
|
|
91
93
|
self._is_processing = False
|
|
92
94
|
|
|
93
|
-
run_as_background_process("stats.notify_new_event",
|
|
95
|
+
self.hs.run_as_background_process("stats.notify_new_event", process)
|
|
94
96
|
|
|
95
97
|
async def _unsafe_process(self) -> None:
|
|
96
98
|
# If self.pos is None then means we haven't fetched it from DB
|
synapse/handlers/sync.py
CHANGED
|
@@ -323,6 +323,7 @@ class SyncHandler:
|
|
|
323
323
|
] = ExpiringCache(
|
|
324
324
|
cache_name="lazy_loaded_members_cache",
|
|
325
325
|
server_name=self.server_name,
|
|
326
|
+
hs=hs,
|
|
326
327
|
clock=self.clock,
|
|
327
328
|
max_len=0,
|
|
328
329
|
expiry_ms=LAZY_LOADED_MEMBERS_CACHE_MAX_AGE,
|
|
@@ -552,7 +553,7 @@ class SyncHandler:
|
|
|
552
553
|
Returns:
|
|
553
554
|
A tuple of the now StreamToken, updated to reflect the which typing
|
|
554
555
|
events are included, and a dict mapping from room_id to a list of
|
|
555
|
-
|
|
556
|
+
ephemeral events for that room.
|
|
556
557
|
"""
|
|
557
558
|
|
|
558
559
|
sync_config = sync_result_builder.sync_config
|
|
@@ -577,12 +578,8 @@ class SyncHandler:
|
|
|
577
578
|
ephemeral_by_room: JsonDict = {}
|
|
578
579
|
|
|
579
580
|
for event in typing:
|
|
580
|
-
# we want to exclude the room_id from the event, but modifying the
|
|
581
|
-
# result returned by the event source is poor form (it might cache
|
|
582
|
-
# the object)
|
|
583
581
|
room_id = event["room_id"]
|
|
584
|
-
|
|
585
|
-
ephemeral_by_room.setdefault(room_id, []).append(event_copy)
|
|
582
|
+
ephemeral_by_room.setdefault(room_id, []).append(event)
|
|
586
583
|
|
|
587
584
|
receipt_key = (
|
|
588
585
|
since_token.receipt_key
|
|
@@ -602,9 +599,7 @@ class SyncHandler:
|
|
|
602
599
|
|
|
603
600
|
for event in receipts:
|
|
604
601
|
room_id = event["room_id"]
|
|
605
|
-
|
|
606
|
-
event_copy = {k: v for (k, v) in event.items() if k != "room_id"}
|
|
607
|
-
ephemeral_by_room.setdefault(room_id, []).append(event_copy)
|
|
602
|
+
ephemeral_by_room.setdefault(room_id, []).append(event)
|
|
608
603
|
|
|
609
604
|
return now_token, ephemeral_by_room
|
|
610
605
|
|
|
@@ -980,7 +975,11 @@ class SyncHandler:
|
|
|
980
975
|
)
|
|
981
976
|
if cache is None:
|
|
982
977
|
logger.debug("creating LruCache for %r", cache_key)
|
|
983
|
-
cache = LruCache(
|
|
978
|
+
cache = LruCache(
|
|
979
|
+
max_size=LAZY_LOADED_MEMBERS_CACHE_MAX_SIZE,
|
|
980
|
+
clock=self.clock,
|
|
981
|
+
server_name=self.server_name,
|
|
982
|
+
)
|
|
984
983
|
self.lazy_loaded_members_cache[cache_key] = cache
|
|
985
984
|
else:
|
|
986
985
|
logger.debug("found LruCache for %r", cache_key)
|
|
@@ -2729,9 +2728,17 @@ class SyncHandler:
|
|
|
2729
2728
|
)
|
|
2730
2729
|
)
|
|
2731
2730
|
|
|
2732
|
-
ephemeral =
|
|
2733
|
-
ephemeral
|
|
2734
|
-
|
|
2731
|
+
ephemeral = [
|
|
2732
|
+
# per spec, ephemeral events (typing notifications and read receipts)
|
|
2733
|
+
# should not have a `room_id` field when sent to clients
|
|
2734
|
+
# refs:
|
|
2735
|
+
# - https://spec.matrix.org/v1.16/client-server-api/#mtyping
|
|
2736
|
+
# - https://spec.matrix.org/v1.16/client-server-api/#mreceipt
|
|
2737
|
+
{k: v for (k, v) in event.items() if k != "room_id"}
|
|
2738
|
+
for event in await sync_config.filter_collection.filter_room_ephemeral(
|
|
2739
|
+
ephemeral
|
|
2740
|
+
)
|
|
2741
|
+
]
|
|
2735
2742
|
|
|
2736
2743
|
if not (
|
|
2737
2744
|
always_include
|
synapse/handlers/typing.py
CHANGED
|
@@ -28,7 +28,6 @@ from synapse.api.constants import EduTypes
|
|
|
28
28
|
from synapse.api.errors import AuthError, ShadowBanError, SynapseError
|
|
29
29
|
from synapse.appservice import ApplicationService
|
|
30
30
|
from synapse.metrics.background_process_metrics import (
|
|
31
|
-
run_as_background_process,
|
|
32
31
|
wrap_as_background_process,
|
|
33
32
|
)
|
|
34
33
|
from synapse.replication.tcp.streams import TypingStream
|
|
@@ -78,11 +77,10 @@ class FollowerTypingHandler:
|
|
|
78
77
|
"""
|
|
79
78
|
|
|
80
79
|
def __init__(self, hs: "HomeServer"):
|
|
80
|
+
self.hs = hs # nb must be called this for @wrap_as_background_process
|
|
81
81
|
self.store = hs.get_datastores().main
|
|
82
82
|
self._storage_controllers = hs.get_storage_controllers()
|
|
83
|
-
self.server_name =
|
|
84
|
-
hs.hostname
|
|
85
|
-
) # nb must be called this for @wrap_as_background_process
|
|
83
|
+
self.server_name = hs.hostname
|
|
86
84
|
self.clock = hs.get_clock()
|
|
87
85
|
self.is_mine_id = hs.is_mine_id
|
|
88
86
|
self.is_mine_server_name = hs.is_mine_server_name
|
|
@@ -144,9 +142,8 @@ class FollowerTypingHandler:
|
|
|
144
142
|
if self.federation and self.is_mine_id(member.user_id):
|
|
145
143
|
last_fed_poke = self._member_last_federation_poke.get(member, None)
|
|
146
144
|
if not last_fed_poke or last_fed_poke + FEDERATION_PING_INTERVAL <= now:
|
|
147
|
-
run_as_background_process(
|
|
145
|
+
self.hs.run_as_background_process(
|
|
148
146
|
"typing._push_remote",
|
|
149
|
-
self.server_name,
|
|
150
147
|
self._push_remote,
|
|
151
148
|
member=member,
|
|
152
149
|
typing=True,
|
|
@@ -220,9 +217,8 @@ class FollowerTypingHandler:
|
|
|
220
217
|
self._rooms_updated.add(row.room_id)
|
|
221
218
|
|
|
222
219
|
if self.federation:
|
|
223
|
-
run_as_background_process(
|
|
220
|
+
self.hs.run_as_background_process(
|
|
224
221
|
"_send_changes_in_typing_to_remotes",
|
|
225
|
-
self.server_name,
|
|
226
222
|
self._send_changes_in_typing_to_remotes,
|
|
227
223
|
row.room_id,
|
|
228
224
|
prev_typing,
|
|
@@ -384,9 +380,8 @@ class TypingWriterHandler(FollowerTypingHandler):
|
|
|
384
380
|
def _push_update(self, member: RoomMember, typing: bool) -> None:
|
|
385
381
|
if self.hs.is_mine_id(member.user_id):
|
|
386
382
|
# Only send updates for changes to our own users.
|
|
387
|
-
run_as_background_process(
|
|
383
|
+
self.hs.run_as_background_process(
|
|
388
384
|
"typing._push_remote",
|
|
389
|
-
self.server_name,
|
|
390
385
|
self._push_remote,
|
|
391
386
|
member,
|
|
392
387
|
typing,
|
|
@@ -36,7 +36,6 @@ from synapse.api.constants import (
|
|
|
36
36
|
from synapse.api.errors import Codes, SynapseError
|
|
37
37
|
from synapse.handlers.state_deltas import MatchChange, StateDeltasHandler
|
|
38
38
|
from synapse.metrics import SERVER_NAME_LABEL
|
|
39
|
-
from synapse.metrics.background_process_metrics import run_as_background_process
|
|
40
39
|
from synapse.storage.databases.main.state_deltas import StateDelta
|
|
41
40
|
from synapse.storage.databases.main.user_directory import SearchResult
|
|
42
41
|
from synapse.storage.roommember import ProfileInfo
|
|
@@ -137,11 +136,15 @@ class UserDirectoryHandler(StateDeltasHandler):
|
|
|
137
136
|
|
|
138
137
|
# We kick this off so that we don't have to wait for a change before
|
|
139
138
|
# we start populating the user directory
|
|
140
|
-
self.clock.call_later(
|
|
139
|
+
self.clock.call_later(
|
|
140
|
+
0,
|
|
141
|
+
self.notify_new_event,
|
|
142
|
+
)
|
|
141
143
|
|
|
142
144
|
# Kick off the profile refresh process on startup
|
|
143
145
|
self._refresh_remote_profiles_call_later = self.clock.call_later(
|
|
144
|
-
10,
|
|
146
|
+
10,
|
|
147
|
+
self.kick_off_remote_profile_refresh_process,
|
|
145
148
|
)
|
|
146
149
|
|
|
147
150
|
async def search_users(
|
|
@@ -193,9 +196,7 @@ class UserDirectoryHandler(StateDeltasHandler):
|
|
|
193
196
|
self._is_processing = False
|
|
194
197
|
|
|
195
198
|
self._is_processing = True
|
|
196
|
-
run_as_background_process(
|
|
197
|
-
"user_directory.notify_new_event", self.server_name, process
|
|
198
|
-
)
|
|
199
|
+
self._hs.run_as_background_process("user_directory.notify_new_event", process)
|
|
199
200
|
|
|
200
201
|
async def handle_local_profile_change(
|
|
201
202
|
self, user_id: str, profile: ProfileInfo
|
|
@@ -609,8 +610,8 @@ class UserDirectoryHandler(StateDeltasHandler):
|
|
|
609
610
|
self._is_refreshing_remote_profiles = False
|
|
610
611
|
|
|
611
612
|
self._is_refreshing_remote_profiles = True
|
|
612
|
-
run_as_background_process(
|
|
613
|
-
"user_directory.refresh_remote_profiles",
|
|
613
|
+
self._hs.run_as_background_process(
|
|
614
|
+
"user_directory.refresh_remote_profiles", process
|
|
614
615
|
)
|
|
615
616
|
|
|
616
617
|
async def _unsafe_refresh_remote_profiles(self) -> None:
|
|
@@ -655,8 +656,9 @@ class UserDirectoryHandler(StateDeltasHandler):
|
|
|
655
656
|
if not users:
|
|
656
657
|
return
|
|
657
658
|
_, _, next_try_at_ts = users[0]
|
|
659
|
+
delay = ((next_try_at_ts - self.clock.time_msec()) // 1000) + 2
|
|
658
660
|
self._refresh_remote_profiles_call_later = self.clock.call_later(
|
|
659
|
-
|
|
661
|
+
delay,
|
|
660
662
|
self.kick_off_remote_profile_refresh_process,
|
|
661
663
|
)
|
|
662
664
|
|
|
@@ -692,9 +694,8 @@ class UserDirectoryHandler(StateDeltasHandler):
|
|
|
692
694
|
self._is_refreshing_remote_profiles_for_servers.remove(server_name)
|
|
693
695
|
|
|
694
696
|
self._is_refreshing_remote_profiles_for_servers.add(server_name)
|
|
695
|
-
run_as_background_process(
|
|
697
|
+
self._hs.run_as_background_process(
|
|
696
698
|
"user_directory.refresh_remote_profiles_for_remote_server",
|
|
697
|
-
self.server_name,
|
|
698
699
|
process,
|
|
699
700
|
)
|
|
700
701
|
|
synapse/handlers/worker_lock.py
CHANGED
|
@@ -37,13 +37,13 @@ from weakref import WeakSet
|
|
|
37
37
|
import attr
|
|
38
38
|
|
|
39
39
|
from twisted.internet import defer
|
|
40
|
-
from twisted.internet.interfaces import IReactorTime
|
|
41
40
|
|
|
42
41
|
from synapse.logging.context import PreserveLoggingContext
|
|
43
42
|
from synapse.logging.opentracing import start_active_span
|
|
44
43
|
from synapse.metrics.background_process_metrics import wrap_as_background_process
|
|
45
44
|
from synapse.storage.databases.main.lock import Lock, LockStore
|
|
46
45
|
from synapse.util.async_helpers import timeout_deferred
|
|
46
|
+
from synapse.util.clock import Clock
|
|
47
47
|
from synapse.util.constants import ONE_MINUTE_SECONDS
|
|
48
48
|
|
|
49
49
|
if TYPE_CHECKING:
|
|
@@ -66,10 +66,8 @@ class WorkerLocksHandler:
|
|
|
66
66
|
"""
|
|
67
67
|
|
|
68
68
|
def __init__(self, hs: "HomeServer") -> None:
|
|
69
|
-
self.
|
|
70
|
-
|
|
71
|
-
) # nb must be called this for @wrap_as_background_process
|
|
72
|
-
self._reactor = hs.get_reactor()
|
|
69
|
+
self.hs = hs # nb must be called this for @wrap_as_background_process
|
|
70
|
+
self._clock = hs.get_clock()
|
|
73
71
|
self._store = hs.get_datastores().main
|
|
74
72
|
self._clock = hs.get_clock()
|
|
75
73
|
self._notifier = hs.get_notifier()
|
|
@@ -98,7 +96,7 @@ class WorkerLocksHandler:
|
|
|
98
96
|
"""
|
|
99
97
|
|
|
100
98
|
lock = WaitingLock(
|
|
101
|
-
|
|
99
|
+
clock=self._clock,
|
|
102
100
|
store=self._store,
|
|
103
101
|
handler=self,
|
|
104
102
|
lock_name=lock_name,
|
|
@@ -129,7 +127,7 @@ class WorkerLocksHandler:
|
|
|
129
127
|
"""
|
|
130
128
|
|
|
131
129
|
lock = WaitingLock(
|
|
132
|
-
|
|
130
|
+
clock=self._clock,
|
|
133
131
|
store=self._store,
|
|
134
132
|
handler=self,
|
|
135
133
|
lock_name=lock_name,
|
|
@@ -160,7 +158,7 @@ class WorkerLocksHandler:
|
|
|
160
158
|
lock = WaitingMultiLock(
|
|
161
159
|
lock_names=lock_names,
|
|
162
160
|
write=write,
|
|
163
|
-
|
|
161
|
+
clock=self._clock,
|
|
164
162
|
store=self._store,
|
|
165
163
|
handler=self,
|
|
166
164
|
)
|
|
@@ -197,7 +195,11 @@ class WorkerLocksHandler:
|
|
|
197
195
|
if not deferred.called:
|
|
198
196
|
deferred.callback(None)
|
|
199
197
|
|
|
200
|
-
self._clock.call_later(
|
|
198
|
+
self._clock.call_later(
|
|
199
|
+
0,
|
|
200
|
+
_wake_all_locks,
|
|
201
|
+
locks,
|
|
202
|
+
)
|
|
201
203
|
|
|
202
204
|
@wrap_as_background_process("_cleanup_locks")
|
|
203
205
|
async def _cleanup_locks(self) -> None:
|
|
@@ -207,7 +209,7 @@ class WorkerLocksHandler:
|
|
|
207
209
|
|
|
208
210
|
@attr.s(auto_attribs=True, eq=False)
|
|
209
211
|
class WaitingLock:
|
|
210
|
-
|
|
212
|
+
clock: Clock
|
|
211
213
|
store: LockStore
|
|
212
214
|
handler: WorkerLocksHandler
|
|
213
215
|
lock_name: str
|
|
@@ -246,10 +248,11 @@ class WaitingLock:
|
|
|
246
248
|
# periodically wake up in case the lock was released but we
|
|
247
249
|
# weren't notified.
|
|
248
250
|
with PreserveLoggingContext():
|
|
251
|
+
timeout = self._get_next_retry_interval()
|
|
249
252
|
await timeout_deferred(
|
|
250
253
|
deferred=self.deferred,
|
|
251
|
-
timeout=
|
|
252
|
-
|
|
254
|
+
timeout=timeout,
|
|
255
|
+
clock=self.clock,
|
|
253
256
|
)
|
|
254
257
|
except Exception:
|
|
255
258
|
pass
|
|
@@ -290,7 +293,7 @@ class WaitingMultiLock:
|
|
|
290
293
|
|
|
291
294
|
write: bool
|
|
292
295
|
|
|
293
|
-
|
|
296
|
+
clock: Clock
|
|
294
297
|
store: LockStore
|
|
295
298
|
handler: WorkerLocksHandler
|
|
296
299
|
|
|
@@ -323,10 +326,11 @@ class WaitingMultiLock:
|
|
|
323
326
|
# periodically wake up in case the lock was released but we
|
|
324
327
|
# weren't notified.
|
|
325
328
|
with PreserveLoggingContext():
|
|
329
|
+
timeout = self._get_next_retry_interval()
|
|
326
330
|
await timeout_deferred(
|
|
327
331
|
deferred=self.deferred,
|
|
328
|
-
timeout=
|
|
329
|
-
|
|
332
|
+
timeout=timeout,
|
|
333
|
+
clock=self.clock,
|
|
330
334
|
)
|
|
331
335
|
except Exception:
|
|
332
336
|
pass
|
synapse/http/client.py
CHANGED
|
@@ -54,7 +54,6 @@ from twisted.internet.interfaces import (
|
|
|
54
54
|
IOpenSSLContextFactory,
|
|
55
55
|
IReactorCore,
|
|
56
56
|
IReactorPluggableNameResolver,
|
|
57
|
-
IReactorTime,
|
|
58
57
|
IResolutionReceiver,
|
|
59
58
|
ITCPTransport,
|
|
60
59
|
)
|
|
@@ -88,6 +87,7 @@ from synapse.logging.opentracing import set_tag, start_active_span, tags
|
|
|
88
87
|
from synapse.metrics import SERVER_NAME_LABEL
|
|
89
88
|
from synapse.types import ISynapseReactor, StrSequence
|
|
90
89
|
from synapse.util.async_helpers import timeout_deferred
|
|
90
|
+
from synapse.util.clock import Clock
|
|
91
91
|
from synapse.util.json import json_decoder
|
|
92
92
|
|
|
93
93
|
if TYPE_CHECKING:
|
|
@@ -165,16 +165,17 @@ def _is_ip_blocked(
|
|
|
165
165
|
_EPSILON = 0.00000001
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
def _make_scheduler(
|
|
169
|
-
reactor: IReactorTime,
|
|
170
|
-
) -> Callable[[Callable[[], object]], IDelayedCall]:
|
|
168
|
+
def _make_scheduler(clock: Clock) -> Callable[[Callable[[], object]], IDelayedCall]:
|
|
171
169
|
"""Makes a schedular suitable for a Cooperator using the given reactor.
|
|
172
170
|
|
|
173
171
|
(This is effectively just a copy from `twisted.internet.task`)
|
|
174
172
|
"""
|
|
175
173
|
|
|
176
174
|
def _scheduler(x: Callable[[], object]) -> IDelayedCall:
|
|
177
|
-
return
|
|
175
|
+
return clock.call_later(
|
|
176
|
+
_EPSILON,
|
|
177
|
+
x,
|
|
178
|
+
)
|
|
178
179
|
|
|
179
180
|
return _scheduler
|
|
180
181
|
|
|
@@ -367,7 +368,7 @@ class BaseHttpClient:
|
|
|
367
368
|
|
|
368
369
|
# We use this for our body producers to ensure that they use the correct
|
|
369
370
|
# reactor.
|
|
370
|
-
self._cooperator = Cooperator(scheduler=_make_scheduler(hs.
|
|
371
|
+
self._cooperator = Cooperator(scheduler=_make_scheduler(hs.get_clock()))
|
|
371
372
|
|
|
372
373
|
async def request(
|
|
373
374
|
self,
|
|
@@ -436,9 +437,9 @@ class BaseHttpClient:
|
|
|
436
437
|
# we use our own timeout mechanism rather than treq's as a workaround
|
|
437
438
|
# for https://twistedmatrix.com/trac/ticket/9534.
|
|
438
439
|
request_deferred = timeout_deferred(
|
|
439
|
-
request_deferred,
|
|
440
|
-
60,
|
|
441
|
-
self.hs.
|
|
440
|
+
deferred=request_deferred,
|
|
441
|
+
timeout=60,
|
|
442
|
+
clock=self.hs.get_clock(),
|
|
442
443
|
)
|
|
443
444
|
|
|
444
445
|
# turn timeouts into RequestTimedOutErrors
|
|
@@ -763,7 +764,11 @@ class BaseHttpClient:
|
|
|
763
764
|
d = read_body_with_max_size(response, output_stream, max_size)
|
|
764
765
|
|
|
765
766
|
# Ensure that the body is not read forever.
|
|
766
|
-
d = timeout_deferred(
|
|
767
|
+
d = timeout_deferred(
|
|
768
|
+
deferred=d,
|
|
769
|
+
timeout=30,
|
|
770
|
+
clock=self.hs.get_clock(),
|
|
771
|
+
)
|
|
767
772
|
|
|
768
773
|
length = await make_deferred_yieldable(d)
|
|
769
774
|
except BodyExceededMaxSize:
|
|
@@ -957,9 +962,9 @@ class ReplicationClient(BaseHttpClient):
|
|
|
957
962
|
# for https://twistedmatrix.com/trac/ticket/9534.
|
|
958
963
|
# (Updated url https://github.com/twisted/twisted/issues/9534)
|
|
959
964
|
request_deferred = timeout_deferred(
|
|
960
|
-
request_deferred,
|
|
961
|
-
60,
|
|
962
|
-
self.hs.
|
|
965
|
+
deferred=request_deferred,
|
|
966
|
+
timeout=60,
|
|
967
|
+
clock=self.hs.get_clock(),
|
|
963
968
|
)
|
|
964
969
|
|
|
965
970
|
# turn timeouts into RequestTimedOutErrors
|
|
@@ -67,6 +67,9 @@ class MatrixFederationAgent:
|
|
|
67
67
|
Args:
|
|
68
68
|
reactor: twisted reactor to use for underlying requests
|
|
69
69
|
|
|
70
|
+
clock: Internal `HomeServer` clock used to track delayed and looping calls.
|
|
71
|
+
Should be obtained from `hs.get_clock()`.
|
|
72
|
+
|
|
70
73
|
tls_client_options_factory:
|
|
71
74
|
factory to use for fetching client tls options, or none to disable TLS.
|
|
72
75
|
|
|
@@ -97,6 +100,7 @@ class MatrixFederationAgent:
|
|
|
97
100
|
*,
|
|
98
101
|
server_name: str,
|
|
99
102
|
reactor: ISynapseReactor,
|
|
103
|
+
clock: Clock,
|
|
100
104
|
tls_client_options_factory: Optional[FederationPolicyForHTTPS],
|
|
101
105
|
user_agent: bytes,
|
|
102
106
|
ip_allowlist: Optional[IPSet],
|
|
@@ -109,6 +113,7 @@ class MatrixFederationAgent:
|
|
|
109
113
|
Args:
|
|
110
114
|
server_name: Our homeserver name (used to label metrics) (`hs.hostname`).
|
|
111
115
|
reactor
|
|
116
|
+
clock: Should be the `hs` clock from `hs.get_clock()`
|
|
112
117
|
tls_client_options_factory
|
|
113
118
|
user_agent
|
|
114
119
|
ip_allowlist
|
|
@@ -124,7 +129,6 @@ class MatrixFederationAgent:
|
|
|
124
129
|
# addresses, to prevent DNS rebinding.
|
|
125
130
|
reactor = BlocklistingReactorWrapper(reactor, ip_allowlist, ip_blocklist)
|
|
126
131
|
|
|
127
|
-
self._clock = Clock(reactor)
|
|
128
132
|
self._pool = HTTPConnectionPool(reactor)
|
|
129
133
|
self._pool.retryAutomatically = False
|
|
130
134
|
self._pool.maxPersistentPerHost = 5
|
|
@@ -147,6 +151,7 @@ class MatrixFederationAgent:
|
|
|
147
151
|
_well_known_resolver = WellKnownResolver(
|
|
148
152
|
server_name=server_name,
|
|
149
153
|
reactor=reactor,
|
|
154
|
+
clock=clock,
|
|
150
155
|
agent=BlocklistingAgentWrapper(
|
|
151
156
|
ProxyAgent(
|
|
152
157
|
reactor=reactor,
|
|
@@ -90,6 +90,7 @@ class WellKnownResolver:
|
|
|
90
90
|
self,
|
|
91
91
|
server_name: str,
|
|
92
92
|
reactor: ISynapseThreadlessReactor,
|
|
93
|
+
clock: Clock,
|
|
93
94
|
agent: IAgent,
|
|
94
95
|
user_agent: bytes,
|
|
95
96
|
well_known_cache: Optional[TTLCache[bytes, Optional[bytes]]] = None,
|
|
@@ -99,6 +100,7 @@ class WellKnownResolver:
|
|
|
99
100
|
Args:
|
|
100
101
|
server_name: Our homeserver name (used to label metrics) (`hs.hostname`).
|
|
101
102
|
reactor
|
|
103
|
+
clock: Should be the `hs` clock from `hs.get_clock()`
|
|
102
104
|
agent
|
|
103
105
|
user_agent
|
|
104
106
|
well_known_cache
|
|
@@ -107,7 +109,7 @@ class WellKnownResolver:
|
|
|
107
109
|
|
|
108
110
|
self.server_name = server_name
|
|
109
111
|
self._reactor = reactor
|
|
110
|
-
self._clock =
|
|
112
|
+
self._clock = clock
|
|
111
113
|
|
|
112
114
|
if well_known_cache is None:
|
|
113
115
|
well_known_cache = TTLCache(
|