hypha-rpc 0.20.88__py3-none-any.whl → 0.20.90__py3-none-any.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.
- hypha_rpc/VERSION +1 -1
- hypha_rpc/http_client.py +78 -1
- {hypha_rpc-0.20.88.dist-info → hypha_rpc-0.20.90.dist-info}/METADATA +1 -1
- {hypha_rpc-0.20.88.dist-info → hypha_rpc-0.20.90.dist-info}/RECORD +6 -6
- {hypha_rpc-0.20.88.dist-info → hypha_rpc-0.20.90.dist-info}/WHEEL +0 -0
- {hypha_rpc-0.20.88.dist-info → hypha_rpc-0.20.90.dist-info}/top_level.txt +0 -0
hypha_rpc/VERSION
CHANGED
hypha_rpc/http_client.py
CHANGED
|
@@ -89,6 +89,7 @@ class HTTPStreamingRPCConnection:
|
|
|
89
89
|
self._closed = False
|
|
90
90
|
self._enable_reconnect = False
|
|
91
91
|
self._stream_task: Optional[asyncio.Task] = None
|
|
92
|
+
self._refresh_token_task: Optional[asyncio.Task] = None
|
|
92
93
|
self._http_client: Optional[httpx.AsyncClient] = None
|
|
93
94
|
|
|
94
95
|
self.connection_info = None
|
|
@@ -108,6 +109,41 @@ class HTTPStreamingRPCConnection:
|
|
|
108
109
|
self._handle_connected = handler
|
|
109
110
|
assert inspect.iscoroutinefunction(handler), "Handler must be async"
|
|
110
111
|
|
|
112
|
+
async def _send_refresh_token(self, token_refresh_interval: float):
|
|
113
|
+
"""Send refresh token request at regular intervals.
|
|
114
|
+
|
|
115
|
+
Similar to WebSocket, this periodically requests a new reconnection token
|
|
116
|
+
to keep the session alive and allow reconnection with a fresh token.
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
await asyncio.sleep(2) # Initial delay
|
|
120
|
+
while not self._closed and self._http_client:
|
|
121
|
+
try:
|
|
122
|
+
# Send refresh token request via POST
|
|
123
|
+
workspace = self._workspace or "public"
|
|
124
|
+
url = f"{self._server_url}/{workspace}/rpc"
|
|
125
|
+
params = {"client_id": self._client_id}
|
|
126
|
+
|
|
127
|
+
refresh_message = msgpack.packb({"type": "refresh_token"})
|
|
128
|
+
response = await self._http_client.post(
|
|
129
|
+
url,
|
|
130
|
+
content=refresh_message,
|
|
131
|
+
params=params,
|
|
132
|
+
headers=self._get_headers(),
|
|
133
|
+
)
|
|
134
|
+
if response.status_code == 200:
|
|
135
|
+
logger.debug("Token refresh requested successfully")
|
|
136
|
+
else:
|
|
137
|
+
logger.warning(f"Token refresh request failed: {response.status_code}")
|
|
138
|
+
except Exception as e:
|
|
139
|
+
logger.warning(f"Failed to send refresh token request: {e}")
|
|
140
|
+
|
|
141
|
+
await asyncio.sleep(token_refresh_interval)
|
|
142
|
+
except asyncio.CancelledError:
|
|
143
|
+
logger.debug("Token refresh task was cancelled")
|
|
144
|
+
except Exception as e:
|
|
145
|
+
logger.error(f"Error in token refresh task: {e}")
|
|
146
|
+
|
|
111
147
|
def _get_headers(self, for_stream: bool = False) -> dict:
|
|
112
148
|
"""Get HTTP headers with authentication.
|
|
113
149
|
|
|
@@ -127,7 +163,11 @@ class HTTPStreamingRPCConnection:
|
|
|
127
163
|
return headers
|
|
128
164
|
|
|
129
165
|
async def _create_http_client(self) -> httpx.AsyncClient:
|
|
130
|
-
"""Create configured HTTP client.
|
|
166
|
+
"""Create configured HTTP client with connection pooling.
|
|
167
|
+
|
|
168
|
+
Connection pooling improves performance by reusing TCP connections
|
|
169
|
+
for multiple requests, reducing connection overhead.
|
|
170
|
+
"""
|
|
131
171
|
verify = True
|
|
132
172
|
if self._ssl is False:
|
|
133
173
|
verify = False
|
|
@@ -137,6 +177,12 @@ class HTTPStreamingRPCConnection:
|
|
|
137
177
|
return httpx.AsyncClient(
|
|
138
178
|
timeout=httpx.Timeout(self._timeout, connect=30.0),
|
|
139
179
|
verify=verify,
|
|
180
|
+
# Connection pooling for better performance with many requests
|
|
181
|
+
limits=httpx.Limits(
|
|
182
|
+
max_connections=100, # Max total connections
|
|
183
|
+
max_keepalive_connections=20, # Keep-alive connections for reuse
|
|
184
|
+
keepalive_expiry=30.0, # Keep connections alive for 30 seconds
|
|
185
|
+
),
|
|
140
186
|
)
|
|
141
187
|
|
|
142
188
|
async def open(self):
|
|
@@ -153,6 +199,11 @@ class HTTPStreamingRPCConnection:
|
|
|
153
199
|
if self._format == "msgpack":
|
|
154
200
|
params["format"] = "msgpack"
|
|
155
201
|
|
|
202
|
+
# Add reconnection token if available (for reconnection)
|
|
203
|
+
if self._reconnection_token:
|
|
204
|
+
params["reconnection_token"] = self._reconnection_token
|
|
205
|
+
logger.info(f"Using reconnection token for HTTP streaming connection")
|
|
206
|
+
|
|
156
207
|
try:
|
|
157
208
|
# Start streaming in background task
|
|
158
209
|
self._stream_task = asyncio.create_task(
|
|
@@ -180,11 +231,27 @@ class HTTPStreamingRPCConnection:
|
|
|
180
231
|
if "reconnection_token" in self.connection_info:
|
|
181
232
|
self._reconnection_token = self.connection_info["reconnection_token"]
|
|
182
233
|
|
|
234
|
+
# Adjust token refresh interval based on server's token lifetime
|
|
235
|
+
if "reconnection_token_life_time" in self.connection_info:
|
|
236
|
+
token_life_time = self.connection_info["reconnection_token_life_time"]
|
|
237
|
+
if self._token_refresh_interval > token_life_time / 1.5:
|
|
238
|
+
logger.warning(
|
|
239
|
+
f"Token refresh interval ({self._token_refresh_interval}s) is too long, "
|
|
240
|
+
f"adjusting to {token_life_time / 1.5:.0f}s based on token lifetime"
|
|
241
|
+
)
|
|
242
|
+
self._token_refresh_interval = token_life_time / 1.5
|
|
243
|
+
|
|
183
244
|
logger.info(
|
|
184
245
|
f"HTTP streaming connected to workspace: {self._workspace}, "
|
|
185
246
|
f"manager_id: {self.manager_id}"
|
|
186
247
|
)
|
|
187
248
|
|
|
249
|
+
# Start token refresh task
|
|
250
|
+
if self._token_refresh_interval > 0:
|
|
251
|
+
self._refresh_token_task = asyncio.create_task(
|
|
252
|
+
self._send_refresh_token(self._token_refresh_interval)
|
|
253
|
+
)
|
|
254
|
+
|
|
188
255
|
if self._handle_connected:
|
|
189
256
|
await self._handle_connected(self.connection_info)
|
|
190
257
|
|
|
@@ -390,6 +457,16 @@ class HTTPStreamingRPCConnection:
|
|
|
390
457
|
|
|
391
458
|
async def _cleanup(self):
|
|
392
459
|
"""Cleanup resources."""
|
|
460
|
+
# Cancel token refresh task
|
|
461
|
+
if self._refresh_token_task and not self._refresh_token_task.done():
|
|
462
|
+
self._refresh_token_task.cancel()
|
|
463
|
+
try:
|
|
464
|
+
await asyncio.wait_for(self._refresh_token_task, timeout=1.0)
|
|
465
|
+
except (asyncio.CancelledError, asyncio.TimeoutError):
|
|
466
|
+
pass
|
|
467
|
+
self._refresh_token_task = None
|
|
468
|
+
|
|
469
|
+
# Cancel stream task
|
|
393
470
|
if self._stream_task and not self._stream_task.done():
|
|
394
471
|
self._stream_task.cancel()
|
|
395
472
|
try:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
hypha_rpc/VERSION,sha256=
|
|
1
|
+
hypha_rpc/VERSION,sha256=ZVATf0qPEEjlHYFpjuXt4stv3jKArnsnCLMeVB4OizU,26
|
|
2
2
|
hypha_rpc/__init__.py,sha256=Nm01vho0uIMXET8-lqxaWTRgoKQD-0SEhpmS9odRed0,4721
|
|
3
3
|
hypha_rpc/client.py,sha256=9c3Qd1bboNiEc_5P4jRLi233VFHyyME8alZYZ5ZZq6s,4551
|
|
4
|
-
hypha_rpc/http_client.py,sha256=
|
|
4
|
+
hypha_rpc/http_client.py,sha256=z1fbomvF9wk7ZxFmzfw8qnheE_ueXrg1C4c8Ss5hgWU,23545
|
|
5
5
|
hypha_rpc/pyodide_sse.py,sha256=o1-6Bqb7bcplSy7pwkmtQb6vKeJsyxex_RebqNd3wX8,2960
|
|
6
6
|
hypha_rpc/pyodide_websocket.py,sha256=XjrgKYySUSNYma-rXjHrSv08YCxj5t4hYEQnK15D6cE,18749
|
|
7
7
|
hypha_rpc/rpc.py,sha256=lnNiPAm_BNT5JjDhAPFRlxs6HioXw77TelUtYd_blYk,115579
|
|
@@ -14,7 +14,7 @@ hypha_rpc/utils/mcp.py,sha256=AW48yjCovc0jyekRLeD_1U8mRaA8-nEqh4DotSE_s3Y,17348
|
|
|
14
14
|
hypha_rpc/utils/pydantic.py,sha256=a09_ys4BSXc4Yi6OgZjdspbtLvQVoRCChr6uInY4fN4,5144
|
|
15
15
|
hypha_rpc/utils/schema.py,sha256=WabBJiDheMKRXUroVe9JRlI5P4Wlv6kc0roxVNQZHH8,22110
|
|
16
16
|
hypha_rpc/utils/serve.py,sha256=xr_3oAQDyignQbz1fcm4kuRMBOb52-i0VSYCjZou51c,11882
|
|
17
|
-
hypha_rpc-0.20.
|
|
18
|
-
hypha_rpc-0.20.
|
|
19
|
-
hypha_rpc-0.20.
|
|
20
|
-
hypha_rpc-0.20.
|
|
17
|
+
hypha_rpc-0.20.90.dist-info/METADATA,sha256=UXm7RkCI9fWyXujOHJlWhN4Pwp883CZi0ut1075FMp4,924
|
|
18
|
+
hypha_rpc-0.20.90.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
19
|
+
hypha_rpc-0.20.90.dist-info/top_level.txt,sha256=uShPbaPGP-Ig8OVnQcT6sEzV0Qhb6wfxSJ3uCmYaB58,10
|
|
20
|
+
hypha_rpc-0.20.90.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|