Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 0a3e324

Browse files
committed
Wait for connection to exporter to be ready on unix socket
Waits for the unix socket connection to actually be able to create a client and run GetReport before the client can continue. This works for the pytest wrapper, jmp shell, or bare python client usage. Fixes-Issue: #680
1 parent def3107 commit 0a3e324

File tree

1 file changed

+28
-1
lines changed
  • packages/jumpstarter/jumpstarter/client

1 file changed

+28
-1
lines changed

packages/jumpstarter/jumpstarter/client/lease.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
sleep,
1919
)
2020
from anyio.from_thread import BlockingPortal
21-
from grpc.aio import Channel
21+
from grpc.aio import AioRpcError, Channel
2222
from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc
2323

2424
from .exceptions import LeaseError
2525
from jumpstarter.client import client_from_path
2626
from jumpstarter.client.grpc import ClientService
2727
from jumpstarter.common import TemporaryUnixListener
2828
from jumpstarter.common.condition import condition_false, condition_message, condition_present_and_equal, condition_true
29+
from jumpstarter.common.exceptions import ConnectionError
2930
from jumpstarter.common.grpc import translate_grpc_exceptions
3031
from jumpstarter.common.streams import connect_router_stream
3132
from jumpstarter.config.tls import TLSConfigV1Alpha1
@@ -189,8 +190,34 @@ async def handle_async(self, stream):
189190
@asynccontextmanager
190191
async def serve_unix_async(self):
191192
async with TemporaryUnixListener(self.handle_async) as path:
193+
logger.debug("Serving Unix socket at %s", path)
194+
await self._wait_for_ready_connection(path)
195+
# TODO: talk to the exporter to make sure it's ready.... (once we have the hooks)
192196
yield path
193197

198+
async def _wait_for_ready_connection(self, path: str):
199+
retries_left = 5
200+
logger.info("Waiting for ready connection at %s", path)
201+
while True:
202+
try:
203+
with ExitStack() as stack:
204+
async with client_from_path(path, self.portal, stack, allow=self.allow, unsafe=self.unsafe) as _:
205+
break
206+
except AioRpcError as e:
207+
if retries_left > 1:
208+
retries_left -= 1
209+
else:
210+
logger.error("Max retries reached while waiting for ready connection at %s", path)
211+
raise ConnectionError("Max retries reached while waiting for ready connection at %s" % path) from e
212+
if e.code().name == "UNAVAILABLE":
213+
logger.warning("Still waiting for connection to be ready at %s", path)
214+
else:
215+
logger.warning("Waiting for ready connection to %s: %s", path, e)
216+
await sleep(5)
217+
except Exception as e:
218+
logger.error("Unexpected error while waiting for ready connection to %s: %s", path, e)
219+
raise ConnectionError("Unexpected error while waiting for ready connection to %s" % path) from e
220+
194221
@asynccontextmanager
195222
async def monitor_async(self, threshold: timedelta = timedelta(minutes=5)):
196223
async def _monitor():

0 commit comments

Comments
 (0)