From 6a33c58fc3acb605a3e793ee2742d04de87b731c Mon Sep 17 00:00:00 2001 From: shcherbak Date: Mon, 29 Dec 2025 01:41:03 +0200 Subject: [PATCH 1/4] set worker_name compatible with k8s horizontal pod autoscaling --- synapse/config/workers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/synapse/config/workers.py b/synapse/config/workers.py index ec8ab9506bc..81590d0e10d 100644 --- a/synapse/config/workers.py +++ b/synapse/config/workers.py @@ -23,6 +23,7 @@ import argparse import logging from typing import Any +from os import environ import attr from pydantic import ( @@ -258,7 +259,9 @@ def read_config( ) self.worker_replication_secret = worker_replication_secret - self.worker_name = config.get("worker_name", self.worker_app) + self.worker_name = self.worker_app + if self.worker_app: + self.worker_name = config.get("worker_name", environ.get("HOSTNAME")) self.instance_name = self.worker_name or MAIN_PROCESS_INSTANCE_NAME # FIXME: Remove this check after a suitable amount of time. From 9c0a97d50c17a9f36e01e588f7f2b9b802f98bab Mon Sep 17 00:00:00 2001 From: shcherbak Date: Fri, 26 Jun 2026 23:56:57 +0300 Subject: [PATCH 2/4] presence: run set_state in background during user_syncing to unblock sync user_syncing() was awaiting set_state() before returning the context manager, causing every /sync request to block on presence I/O (DB read/write on the presence writer, or an HTTP RPC from workers). Move the counter increment and mark_as_coming_online ahead of the call, then fire set_state via run_in_background consistent with how _end() is already handled. --- synapse/handlers/presence.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py index 4c3adca46e3..8b5d25089c3 100644 --- a/synapse/handlers/presence.py +++ b/synapse/handlers/presence.py @@ -601,15 +601,6 @@ async def user_syncing( if not affect_presence or not self._track_presence: return _NullContextManager() - # Note that this causes last_active_ts to be incremented which is not - # what the spec wants. - await self.set_state( - UserID.from_string(user_id), - device_id, - state={"presence": presence_state}, - is_sync=True, - ) - curr_sync = self._user_device_to_num_current_syncs.get((user_id, device_id), 0) self._user_device_to_num_current_syncs[(user_id, device_id)] = curr_sync + 1 @@ -617,6 +608,16 @@ async def user_syncing( if self._user_device_to_num_current_syncs[(user_id, device_id)] == 1: self.mark_as_coming_online(user_id, device_id) + # Note that this causes last_active_ts to be incremented which is not + # what the spec wants. Run in background to avoid blocking sync start. + run_in_background( + self.set_state, + UserID.from_string(user_id), + device_id, + {"presence": presence_state}, + is_sync=True, + ) + def _end() -> None: # We check that the user_id is in user_to_num_current_syncs because # user_to_num_current_syncs may have been cleared if we are @@ -1178,11 +1179,12 @@ async def user_syncing( self._user_device_to_num_current_syncs[(user_id, device_id)] = curr_sync + 1 # Note that this causes last_active_ts to be incremented which is not - # what the spec wants. - await self.set_state( + # what the spec wants. Run in background to avoid blocking sync start. + run_in_background( + self.set_state, UserID.from_string(user_id), device_id, - state={"presence": presence_state}, + {"presence": presence_state}, is_sync=True, ) From 8a6fa1626761ad1cf030b648f40e8b11b0cb356e Mon Sep 17 00:00:00 2001 From: shcherbak Date: Fri, 26 Jun 2026 23:59:29 +0300 Subject: [PATCH 3/4] presence: run set_state in background during user_syncing to unblock sync user_syncing() was awaiting set_state() before returning the context manager, causing every /sync request to block on presence I/O (DB read/write on the presence writer, or an HTTP RPC from workers). Move the counter increment and mark_as_coming_online ahead of the call, then fire set_state via run_in_background consistent with how _end() is already handled. --- synapse/config/workers.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/synapse/config/workers.py b/synapse/config/workers.py index bad7027afca..fb7378bfc81 100644 --- a/synapse/config/workers.py +++ b/synapse/config/workers.py @@ -23,7 +23,6 @@ import argparse import logging from typing import Any -from os import environ import attr from pydantic import ( @@ -267,9 +266,7 @@ def read_config( ) self.worker_replication_secret = worker_replication_secret - self.worker_name = self.worker_app - if self.worker_app: - self.worker_name = config.get("worker_name", environ.get("HOSTNAME")) + self.worker_name = config.get("worker_name", self.worker_app) self.instance_name = self.worker_name or MAIN_PROCESS_INSTANCE_NAME # FIXME: Remove this check after a suitable amount of time. From 9481a3c55e9168a4d19c92dc998692b635bf2a0d Mon Sep 17 00:00:00 2001 From: shcherbak Date: Sat, 27 Jun 2026 00:06:18 +0300 Subject: [PATCH 4/4] presence: run set_state in background during user_syncing to unblock sync user_syncing() was awaiting set_state() before returning the context manager, causing every /sync request to block on presence I/O (DB read/write on the presence writer, or an HTTP RPC from workers). Move the counter increment and mark_as_coming_online ahead of the call, then fire set_state via run_in_background consistent with how _end() is already handled. --- changelog.d/19885.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/19885.bugfix diff --git a/changelog.d/19885.bugfix b/changelog.d/19885.bugfix new file mode 100644 index 00000000000..2b3b779933d --- /dev/null +++ b/changelog.d/19885.bugfix @@ -0,0 +1 @@ +Fix `/sync` being blocked by presence state updates when presence is enabled.