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

Commit f95dc68

Browse files
authored
Merge pull request #762 from jumpstarter-dev/backport-761-to-release-0.7
[Backport release-0.7] fix: lease-acquisition loop can fail with temporary grpc issues
2 parents 0dc9e3a + 0ae14e9 commit f95dc68

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

packages/jumpstarter/jumpstarter/client/lease.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from grpc.aio import AioRpcError, Channel
2424
from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc
2525
from rich.console import Console
26+
from tenacity import retry, retry_if_exception_type, wait_exponential_jitter
2627

2728
from .exceptions import LeaseError
2829
from jumpstarter.client import client_from_path
@@ -77,6 +78,24 @@ async def get(self):
7778
svc = ClientService(channel=self.channel, namespace=self.namespace)
7879
return await svc.GetLease(name=self.name)
7980

81+
@retry(
82+
wait=wait_exponential_jitter(initial=1, max=120, jitter=1),
83+
retry=retry_if_exception_type(ConnectionError),
84+
reraise=True,
85+
)
86+
async def _get_with_retry(self):
87+
"""Get lease with exponential backoff retry on ConnectionError.
88+
89+
Retries with exponential backoff and jitter indefinitely when ConnectionError occurs.
90+
The wait time between retries is capped at 2 minutes (120 seconds).
91+
Jitter helps prevent thundering herd problems when multiple clients retry simultaneously.
92+
"""
93+
try:
94+
return await self.get()
95+
except ConnectionError as e:
96+
logger.error("Error while getting lease %s: %s", self.name, e)
97+
raise
98+
8099
def request(self):
81100
"""Request a lease, or verifies a lease which was already created.
82101
@@ -136,8 +155,7 @@ async def _acquire(self):
136155
with LeaseAcquisitionSpinner(self.name) as spinner:
137156
while True:
138157
logger.debug("Polling Lease %s", self.name)
139-
result = await self.get()
140-
158+
result = await self._get_with_retry()
141159
# lease ready
142160
if condition_true(result.conditions, "Ready"):
143161
logger.debug("Lease %s acquired", self.name)

packages/jumpstarter/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ dependencies = [
1919
"xdg-base-dirs>=6.0.2",
2020
"pydantic-settings>=2.9.1",
2121
"rich>=14.0.0",
22+
"tenacity>=8.2.0",
2223
]
2324

2425
[dependency-groups]

0 commit comments

Comments
 (0)