Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit c334ca6

Browse files
authored
Integrate presence from hotfixes (#3694)
1 parent 04f5d2d commit c334ca6

File tree

17 files changed

+303
-67
lines changed

17 files changed

+303
-67
lines changed

changelog.d/3694.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Synapse's presence functionality can now be disabled with the "use_presence" configuration option.

docs/workers.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,14 @@ regular expressions::
241241

242242
^/_matrix/client/(api/v1|r0|unstable)/keys/upload
243243

244+
If ``use_presence`` is False in the homeserver config, it can also handle REST
245+
endpoints matching the following regular expressions::
246+
247+
^/_matrix/client/(api/v1|r0|unstable)/presence/[^/]+/status
248+
249+
This "stub" presence handler will pass through ``GET`` request but make the
250+
``PUT`` effectively a no-op.
251+
244252
It will proxy any requests it cannot handle to the main synapse instance. It
245253
must therefore be configured with the location of the main instance, via
246254
the ``worker_main_http_uri`` setting in the frontend_proxy worker configuration

synapse/app/_base.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def listen_metrics(bind_addresses, port):
140140
logger.info("Metrics now reporting on %s:%d", host, port)
141141

142142

143-
def listen_tcp(bind_addresses, port, factory, backlog=50):
143+
def listen_tcp(bind_addresses, port, factory, reactor=reactor, backlog=50):
144144
"""
145145
Create a TCP socket for a port and several addresses
146146
"""
@@ -156,7 +156,9 @@ def listen_tcp(bind_addresses, port, factory, backlog=50):
156156
check_bind_error(e, address, bind_addresses)
157157

158158

159-
def listen_ssl(bind_addresses, port, factory, context_factory, backlog=50):
159+
def listen_ssl(
160+
bind_addresses, port, factory, context_factory, reactor=reactor, backlog=50
161+
):
160162
"""
161163
Create an SSL socket for a port and several addresses
162164
"""

synapse/app/frontend_proxy.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from synapse.replication.slave.storage.devices import SlavedDeviceStore
3939
from synapse.replication.slave.storage.registration import SlavedRegistrationStore
4040
from synapse.replication.tcp.client import ReplicationClientHandler
41+
from synapse.rest.client.v1.base import ClientV1RestServlet, client_path_patterns
4142
from synapse.rest.client.v2_alpha._base import client_v2_patterns
4243
from synapse.server import HomeServer
4344
from synapse.storage.engines import create_engine
@@ -49,6 +50,35 @@
4950
logger = logging.getLogger("synapse.app.frontend_proxy")
5051

5152

53+
class PresenceStatusStubServlet(ClientV1RestServlet):
54+
PATTERNS = client_path_patterns("/presence/(?P<user_id>[^/]*)/status")
55+
56+
def __init__(self, hs):
57+
super(PresenceStatusStubServlet, self).__init__(hs)
58+
self.http_client = hs.get_simple_http_client()
59+
self.auth = hs.get_auth()
60+
self.main_uri = hs.config.worker_main_http_uri
61+
62+
@defer.inlineCallbacks
63+
def on_GET(self, request, user_id):
64+
# Pass through the auth headers, if any, in case the access token
65+
# is there.
66+
auth_headers = request.requestHeaders.getRawHeaders("Authorization", [])
67+
headers = {
68+
"Authorization": auth_headers,
69+
}
70+
result = yield self.http_client.get_json(
71+
self.main_uri + request.uri,
72+
headers=headers,
73+
)
74+
defer.returnValue((200, result))
75+
76+
@defer.inlineCallbacks
77+
def on_PUT(self, request, user_id):
78+
yield self.auth.get_user_by_req(request)
79+
defer.returnValue((200, {}))
80+
81+
5282
class KeyUploadServlet(RestServlet):
5383
PATTERNS = client_v2_patterns("/keys/upload(/(?P<device_id>[^/]+))?$")
5484

@@ -135,6 +165,12 @@ def _listen_http(self, listener_config):
135165
elif name == "client":
136166
resource = JsonResource(self, canonical_json=False)
137167
KeyUploadServlet(self).register(resource)
168+
169+
# If presence is disabled, use the stub servlet that does
170+
# not allow sending presence
171+
if not self.config.use_presence:
172+
PresenceStatusStubServlet(self).register(resource)
173+
138174
resources.update({
139175
"/_matrix/client/r0": resource,
140176
"/_matrix/client/unstable": resource,
@@ -153,7 +189,8 @@ def _listen_http(self, listener_config):
153189
listener_config,
154190
root_resource,
155191
self.version_string,
156-
)
192+
),
193+
reactor=self.get_reactor()
157194
)
158195

159196
logger.info("Synapse client reader now listening on port %d", port)

synapse/app/synchrotron.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ def __init__(self, hs):
114114
logger.info("Presence process_id is %r", self.process_id)
115115

116116
def send_user_sync(self, user_id, is_syncing, last_sync_ms):
117-
self.hs.get_tcp_replication().send_user_sync(user_id, is_syncing, last_sync_ms)
117+
if self.hs.config.use_presence:
118+
self.hs.get_tcp_replication().send_user_sync(
119+
user_id, is_syncing, last_sync_ms
120+
)
118121

119122
def mark_as_coming_online(self, user_id):
120123
"""A user has started syncing. Send a UserSync to the master, unless they
@@ -211,10 +214,13 @@ def process_replication_rows(self, token, rows):
211214
yield self.notify_from_replication(states, stream_id)
212215

213216
def get_currently_syncing_users(self):
214-
return [
215-
user_id for user_id, count in iteritems(self.user_to_num_current_syncs)
216-
if count > 0
217-
]
217+
if self.hs.config.use_presence:
218+
return [
219+
user_id for user_id, count in iteritems(self.user_to_num_current_syncs)
220+
if count > 0
221+
]
222+
else:
223+
return set()
218224

219225

220226
class SynchrotronTyping(object):

synapse/config/server.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def read_config(self, config):
4949
# "disable" federation
5050
self.send_federation = config.get("send_federation", True)
5151

52+
# Whether to enable user presence.
53+
self.use_presence = config.get("use_presence", True)
54+
5255
# Whether to update the user directory or not. This should be set to
5356
# false only if we are updating the user directory in a worker
5457
self.update_user_directory = config.get("update_user_directory", True)
@@ -250,6 +253,9 @@ def default_config(self, server_name, **kwargs):
250253
# hard limit.
251254
soft_file_limit: 0
252255
256+
# Set to false to disable presence tracking on this homeserver.
257+
use_presence: true
258+
253259
# The GC threshold parameters to pass to `gc.set_threshold`, if defined
254260
# gc_thresholds: [700, 10, 10]
255261

synapse/federation/transaction_queue.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class TransactionQueue(object):
5858
"""
5959

6060
def __init__(self, hs):
61+
self.hs = hs
6162
self.server_name = hs.hostname
6263

6364
self.store = hs.get_datastore()
@@ -308,6 +309,9 @@ def send_presence(self, states):
308309
Args:
309310
states (list(UserPresenceState))
310311
"""
312+
if not self.hs.config.use_presence:
313+
# No-op if presence is disabled.
314+
return
311315

312316
# First we queue up the new presence by user ID, so multiple presence
313317
# updates in quick successtion are correctly handled

synapse/handlers/initial_sync.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,10 @@ def _room_initial_sync_joined(self, user_id, room_id, pagin_config,
372372

373373
@defer.inlineCallbacks
374374
def get_presence():
375+
# If presence is disabled, return an empty list
376+
if not self.hs.config.use_presence:
377+
defer.returnValue([])
378+
375379
states = yield presence_handler.get_states(
376380
[m.user_id for m in room_members],
377381
as_event=True,

synapse/handlers/presence.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,10 @@ def bump_presence_active_time(self, user):
395395
"""We've seen the user do something that indicates they're interacting
396396
with the app.
397397
"""
398+
# If presence is disabled, no-op
399+
if not self.hs.config.use_presence:
400+
return
401+
398402
user_id = user.to_string()
399403

400404
bump_active_time_counter.inc()
@@ -424,6 +428,11 @@ def user_syncing(self, user_id, affect_presence=True):
424428
Useful for streams that are not associated with an actual
425429
client that is being used by a user.
426430
"""
431+
# Override if it should affect the user's presence, if presence is
432+
# disabled.
433+
if not self.hs.config.use_presence:
434+
affect_presence = False
435+
427436
if affect_presence:
428437
curr_sync = self.user_to_num_current_syncs.get(user_id, 0)
429438
self.user_to_num_current_syncs[user_id] = curr_sync + 1
@@ -469,13 +478,16 @@ def get_currently_syncing_users(self):
469478
Returns:
470479
set(str): A set of user_id strings.
471480
"""
472-
syncing_user_ids = {
473-
user_id for user_id, count in self.user_to_num_current_syncs.items()
474-
if count
475-
}
476-
for user_ids in self.external_process_to_current_syncs.values():
477-
syncing_user_ids.update(user_ids)
478-
return syncing_user_ids
481+
if self.hs.config.use_presence:
482+
syncing_user_ids = {
483+
user_id for user_id, count in self.user_to_num_current_syncs.items()
484+
if count
485+
}
486+
for user_ids in self.external_process_to_current_syncs.values():
487+
syncing_user_ids.update(user_ids)
488+
return syncing_user_ids
489+
else:
490+
return set()
479491

480492
@defer.inlineCallbacks
481493
def update_external_syncs_row(self, process_id, user_id, is_syncing, sync_time_msec):

synapse/handlers/sync.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ def __nonzero__(self):
185185
class SyncHandler(object):
186186

187187
def __init__(self, hs):
188+
self.hs_config = hs.config
188189
self.store = hs.get_datastore()
189190
self.notifier = hs.get_notifier()
190191
self.presence_handler = hs.get_presence_handler()
@@ -860,7 +861,7 @@ def generate_sync_result(self, sync_config, since_token=None, full_state=False):
860861
since_token is None and
861862
sync_config.filter_collection.blocks_all_presence()
862863
)
863-
if not block_all_presence_data:
864+
if self.hs_config.use_presence and not block_all_presence_data:
864865
yield self._generate_sync_entry_for_presence(
865866
sync_result_builder, newly_joined_rooms, newly_joined_users
866867
)

0 commit comments

Comments
 (0)