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

Commit 3f9449b

Browse files
improve client's lease monitoring
we monitor lease status too frequently (every 5s) which doesn't correspond to the default grpc keepalive which we just made longer. Let's lighten the load a bit and poll less frequent, once in 30s. Changed the info message about lease expiring soon to more friendly "ending in 5 minutes". Also, use effective_begin_time + effective_duration for end time calculation. Once scheduled leases are implemented these may differ from begin_time and duration.
1 parent 7890749 commit 3f9449b

2 files changed

Lines changed: 16 additions & 12 deletions

File tree

packages/jumpstarter/jumpstarter/client/grpc.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class Lease(BaseModel):
114114
name: str
115115
selector: str
116116
duration: timedelta
117+
effective_duration: timedelta | None = None
117118
client: str
118119
exporter: str
119120
conditions: list[kubernetes_pb2.Condition]
@@ -138,8 +139,12 @@ def from_protobuf(cls, data: client_pb2.Lease) -> Lease:
138139
else:
139140
exporter = ""
140141

142+
effective_duration = None
143+
if data.HasField("effective_duration"):
144+
effective_duration = data.effective_duration.ToTimedelta()
145+
141146
effective_begin_time = None
142-
if data.effective_begin_time:
147+
if data.HasField("effective_begin_time"):
143148
effective_begin_time = data.effective_begin_time.ToDatetime(
144149
tzinfo=datetime.now().astimezone().tzinfo,
145150
)
@@ -149,6 +154,7 @@ def from_protobuf(cls, data: client_pb2.Lease) -> Lease:
149154
name=name,
150155
selector=data.selector,
151156
duration=data.duration.ToTimedelta(),
157+
effective_duration=effective_duration,
152158
client=client,
153159
exporter=exporter,
154160
effective_begin_time=effective_begin_time,

packages/jumpstarter/jumpstarter/client/lease.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -248,23 +248,21 @@ async def _wait_for_ready_connection(self, path: str):
248248
@asynccontextmanager
249249
async def monitor_async(self, threshold: timedelta = timedelta(minutes=5)):
250250
async def _monitor():
251+
check_interval = 30 # seconds - check periodically for external lease changes
251252
while True:
252253
lease = await self.get()
253-
# TODO: use effective_end_time as the authoritative source for lease end time
254-
if lease.effective_begin_time:
255-
end_time = lease.effective_begin_time + lease.duration
256-
remain = end_time - datetime.now(tz=datetime.now().astimezone().tzinfo)
254+
if lease.effective_begin_time and lease.effective_duration:
255+
end_time = lease.effective_begin_time + lease.effective_duration
256+
remain = end_time - datetime.now().astimezone()
257257
if remain < timedelta(0):
258258
# lease already expired, stopping monitor
259259
logger.info("Lease {} ended at {}".format(self.name, end_time))
260260
break
261-
elif remain < threshold:
262-
# lease expiring soon, check again on expected expiration time in case it's extended
263-
logger.info("Lease {} ending soon in {} at {}".format(self.name, remain, end_time))
264-
await sleep(threshold.total_seconds())
265-
else:
266-
# lease still active, check again in 5 seconds
267-
await sleep(5)
261+
# Log once when entering the threshold window
262+
if threshold - timedelta(seconds=check_interval) <= remain < threshold:
263+
logger.info("Lease {} ending in {} minutes at {}".format(
264+
self.name, int((remain.total_seconds() + 30) // 60), end_time))
265+
await sleep(min(remain.total_seconds(), check_interval))
268266
else:
269267
await sleep(1)
270268

0 commit comments

Comments
 (0)