hypha-rpc 0.20.89__py3-none-any.whl → 0.20.91__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 +67 -0
- {hypha_rpc-0.20.89.dist-info → hypha_rpc-0.20.91.dist-info}/METADATA +1 -1
- {hypha_rpc-0.20.89.dist-info → hypha_rpc-0.20.91.dist-info}/RECORD +6 -6
- {hypha_rpc-0.20.89.dist-info → hypha_rpc-0.20.91.dist-info}/WHEEL +0 -0
- {hypha_rpc-0.20.89.dist-info → hypha_rpc-0.20.91.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
|
|
|
@@ -163,6 +199,11 @@ class HTTPStreamingRPCConnection:
|
|
|
163
199
|
if self._format == "msgpack":
|
|
164
200
|
params["format"] = "msgpack"
|
|
165
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
|
+
|
|
166
207
|
try:
|
|
167
208
|
# Start streaming in background task
|
|
168
209
|
self._stream_task = asyncio.create_task(
|
|
@@ -190,11 +231,27 @@ class HTTPStreamingRPCConnection:
|
|
|
190
231
|
if "reconnection_token" in self.connection_info:
|
|
191
232
|
self._reconnection_token = self.connection_info["reconnection_token"]
|
|
192
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
|
+
|
|
193
244
|
logger.info(
|
|
194
245
|
f"HTTP streaming connected to workspace: {self._workspace}, "
|
|
195
246
|
f"manager_id: {self.manager_id}"
|
|
196
247
|
)
|
|
197
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
|
+
|
|
198
255
|
if self._handle_connected:
|
|
199
256
|
await self._handle_connected(self.connection_info)
|
|
200
257
|
|
|
@@ -400,6 +457,16 @@ class HTTPStreamingRPCConnection:
|
|
|
400
457
|
|
|
401
458
|
async def _cleanup(self):
|
|
402
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
|
|
403
470
|
if self._stream_task and not self._stream_task.done():
|
|
404
471
|
self._stream_task.cancel()
|
|
405
472
|
try:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
hypha_rpc/VERSION,sha256=
|
|
1
|
+
hypha_rpc/VERSION,sha256=j1kFO_lywKnDlLe-woiBFEziTNuwai-qeVyGIhLgkhY,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.91.dist-info/METADATA,sha256=rIb0SqctYBNrj2IrRKSUBj2UBhAP1VFFECVRsScmAeg,924
|
|
18
|
+
hypha_rpc-0.20.91.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
19
|
+
hypha_rpc-0.20.91.dist-info/top_level.txt,sha256=uShPbaPGP-Ig8OVnQcT6sEzV0Qhb6wfxSJ3uCmYaB58,10
|
|
20
|
+
hypha_rpc-0.20.91.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|