From 373eda4c28bc84aa88b7c3dfd0a83c6efcf2c35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Baki=20Burak=20=C3=96=C4=9F=C3=BCn?= <63836730+bakiburakogun@users.noreply.github.com> Date: Sat, 29 Aug 2026 08:29:06 +0300 Subject: [PATCH 1/2] fix(embeddings): bound the connection separately from the read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The embedding request passed a single timeout value, so nothing bounded establishing the connection. When the TLS handshake to the embedding service stalls — TCP connects, the handshake never completes — the worker waits in recv for the whole request_timeout, 1800 s by default. That stops more than the one request: files_indexing_thread waits for every worker of the batch, so one stalled handshake holds up the batch and no further queue items are fetched until it returns. Give the connection its own bound so the retry already implemented in _get_embedding() can land on a healthy connection. On our deployment this took worker durations from ~300 s, all finishing together at the timeout, to 1.4-85 s, and indexing from 5.2 to 60-65 documents per minute. Fixes #345 Signed-off-by: Baki Burak Öğün <63836730+bakiburakogun@users.noreply.github.com> --- context_chat_backend/network_em.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/context_chat_backend/network_em.py b/context_chat_backend/network_em.py index 5ba8faf5..f0debd08 100644 --- a/context_chat_backend/network_em.py +++ b/context_chat_backend/network_em.py @@ -23,6 +23,10 @@ logger = logging.getLogger('ccb.nextwork_em') TCP_CONNECT_TIMEOUT = 2.0 # seconds +# Connection timeout for the embedding requests, kept apart from the read timeout: +# a stalled TLS handshake would otherwise hold a worker for the whole +# request_timeout, and the batch waits for every worker in it. +HTTP_CONNECT_TIMEOUT = 15 # seconds # Copied from llama_cpp/llama_types.py @@ -99,7 +103,7 @@ def _get_embedding(self, input_: str | list[str], try_: int = 3) -> list[float] response = niquests.post( f'{emconf.base_url.removesuffix("/")}/embeddings', json=data, - timeout=emconf.request_timeout, + timeout=(HTTP_CONNECT_TIMEOUT, emconf.request_timeout), auth=auth, verify=self.app_config.verify_ssl, ) From 78a28b6132234be5df8b0a084ec512a0aff5e2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Baki=20Burak=20=C3=96=C4=9F=C3=BCn?= <63836730+bakiburakogun@users.noreply.github.com> Date: Tue, 1 Sep 2026 12:23:01 +0300 Subject: [PATCH 2/2] fix(embeddings): use the niquests timeout structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the tuple with niquests.TimeoutConfiguration and drops the comment on the constant, as requested in review. Signed-off-by: Baki Burak Öğün <63836730+bakiburakogun@users.noreply.github.com> --- context_chat_backend/network_em.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/context_chat_backend/network_em.py b/context_chat_backend/network_em.py index f0debd08..49efa6a6 100644 --- a/context_chat_backend/network_em.py +++ b/context_chat_backend/network_em.py @@ -23,9 +23,6 @@ logger = logging.getLogger('ccb.nextwork_em') TCP_CONNECT_TIMEOUT = 2.0 # seconds -# Connection timeout for the embedding requests, kept apart from the read timeout: -# a stalled TLS handshake would otherwise hold a worker for the whole -# request_timeout, and the batch waits for every worker in it. HTTP_CONNECT_TIMEOUT = 15 # seconds # Copied from llama_cpp/llama_types.py @@ -103,7 +100,10 @@ def _get_embedding(self, input_: str | list[str], try_: int = 3) -> list[float] response = niquests.post( f'{emconf.base_url.removesuffix("/")}/embeddings', json=data, - timeout=(HTTP_CONNECT_TIMEOUT, emconf.request_timeout), + timeout=niquests.TimeoutConfiguration( + connect=HTTP_CONNECT_TIMEOUT, + read=emconf.request_timeout, + ), auth=auth, verify=self.app_config.verify_ssl, )