From 099576dbec43b923cd255bc2daf4ce1e50f8ef6e Mon Sep 17 00:00:00 2001 From: weikaiwen Date: Thu, 12 Mar 2026 14:06:54 +0800 Subject: [PATCH 1/3] fix --- src/twinkle_client/http/heartbeat.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/twinkle_client/http/heartbeat.py b/src/twinkle_client/http/heartbeat.py index 4a42f75a..1fa86713 100644 --- a/src/twinkle_client/http/heartbeat.py +++ b/src/twinkle_client/http/heartbeat.py @@ -4,7 +4,7 @@ from typing import Callable, Dict, Optional, Set from .http_utils import http_post -from .utils import TWINKLE_SERVER_URL +from .utils import get_base_url class HeartbeatManager: @@ -33,7 +33,6 @@ def __init__(self): return self._initialized = True - self.server_url = TWINKLE_SERVER_URL # Processor heartbeat management self.processor_ids: Set[str] = set() @@ -52,7 +51,7 @@ def __init__(self): def processor_heartbeat_func(self, processor_id_list: str): response = http_post( - url=f'{self.server_url}/processors/heartbeat', json_data={'processor_id': processor_id_list}) + url=f'{get_base_url()}/processors/heartbeat', json_data={'processor_id': processor_id_list}) response.raise_for_status() def register_processor(self, processor_id: str): From bfd257452a8430ae7d204e228439e2dfaae8aded Mon Sep 17 00:00:00 2001 From: weikaiwen Date: Thu, 12 Mar 2026 15:48:41 +0800 Subject: [PATCH 2/3] fix --- src/twinkle_client/http/utils.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/twinkle_client/http/utils.py b/src/twinkle_client/http/utils.py index ad49ffe1..b6e6be97 100644 --- a/src/twinkle_client/http/utils.py +++ b/src/twinkle_client/http/utils.py @@ -11,19 +11,26 @@ _base_url_context: ContextVar[Optional[str]] = ContextVar('base_url', default=None) _api_key_context: ContextVar[Optional[str]] = ContextVar('api_key', default=None) +# Global fallback for base_url, accessible from all threads (including heartbeat daemon threads). +# ContextVar is thread-local and invisible to background threads, so we also store the URL here. +_global_base_url: Optional[str] = None + # Global static request ID shared across all threads # This ensures heartbeat threads use the same request ID as the main training thread _global_request_id: Optional[str] = None def set_base_url(url: str): - """Set the base URL for HTTP requests in the current context.""" - _base_url_context.set(url.rstrip('/')) + """Set the base URL for HTTP requests in the current context and globally.""" + global _global_base_url + stripped = url.rstrip('/') + _base_url_context.set(stripped) + _global_base_url = stripped def get_base_url() -> Optional[str]: - """Get the current base URL from context or environment variable.""" - return _base_url_context.get() or TWINKLE_SERVER_URL + """Get the current base URL from context, global fallback, or environment variable.""" + return _base_url_context.get() or _global_base_url or TWINKLE_SERVER_URL def clear_base_url(): From 33d9cf03b031ef2e51172339a81350346c193738 Mon Sep 17 00:00:00 2001 From: weikaiwen Date: Thu, 12 Mar 2026 16:12:42 +0800 Subject: [PATCH 3/3] fix --- src/twinkle_client/http/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/twinkle_client/http/utils.py b/src/twinkle_client/http/utils.py index b6e6be97..dd50a740 100644 --- a/src/twinkle_client/http/utils.py +++ b/src/twinkle_client/http/utils.py @@ -34,8 +34,10 @@ def get_base_url() -> Optional[str]: def clear_base_url(): - """Clear the base URL context, falling back to environment variable.""" + """Clear the base URL context and global fallback, falling back to environment variable.""" + global _global_base_url _base_url_context.set(None) + _global_base_url = None def set_api_key(api_key: str):