Skip to content

fix: release lease on unused timeout when hooks are configured#598

Open
raballew wants to merge 1 commit intojumpstarter-dev:mainfrom
raballew:051-unused-lease-timeout-dos
Open

fix: release lease on unused timeout when hooks are configured#598
raballew wants to merge 1 commit intojumpstarter-dev:mainfrom
raballew:051-unused-lease-timeout-dos

Conversation

@raballew
Copy link
Copy Markdown
Member

When a lease times out without any client connection and hooks are configured, _cleanup_after_lease skipped the afterLease hook (correct) but also skipped calling _request_lease_release (bug). This left the exporter permanently stuck in LeaseReady status because the controller was never notified that the lease should be freed.

Add _request_lease_release() call in the else branch of _cleanup_after_lease so the controller always frees the lease, regardless of whether the afterLease hook ran.

Fixes: #237

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 52f68b64-3d88-4650-beec-311861a210d0

📥 Commits

Reviewing files that changed from the base of the PR and between 1fcdcef and d3815de.

📒 Files selected for processing (2)
  • python/packages/jumpstarter/jumpstarter/exporter/exporter.py
  • python/packages/jumpstarter/jumpstarter/exporter/exporter_test.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • python/packages/jumpstarter/jumpstarter/exporter/exporter.py
  • python/packages/jumpstarter/jumpstarter/exporter/exporter_test.py

📝 Walkthrough

Walkthrough

Added an awaited call to self._request_lease_release() in Exporter._cleanup_after_lease() on the shutdown branch when a lease ends unused; added tests asserting the lease-release request is invoked once in several end-of-lease scenarios.

Changes

Cohort / File(s) Summary
Exporter shutdown cleanup
python/packages/jumpstarter/jumpstarter/exporter/exporter.py
Await self._request_lease_release() in _cleanup_after_lease() when _stop_requested is true and the AVAILABLE status path is skipped.
Tests for lease-release behavior
python/packages/jumpstarter/jumpstarter/exporter/exporter_test.py
Add three async tests under TestUnusedLeaseTimeout verifying _request_lease_release is awaited exactly once when a lease ends with no client: with hooks, without hooks, and during exporter shutdown (ensuring AVAILABLE not reported in shutdown case).

Sequence Diagram(s)

(omitted — change is a localized cleanup plus tests; no multi-component new flow requiring diagram)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • evakhoni
  • kirkbrauer
  • mangelajo

Poem

🐰 A quiet lease that never found a friend,
I nudged the shutdown path to send an end,
One gentle request, released to the sky,
Hops of relief as leases say goodbye 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a lease release call when hooks are configured and a lease times out.
Description check ✅ Passed The description clearly explains the bug (skipped _request_lease_release when hooks are configured) and the fix (adding the call in the else branch).
Linked Issues check ✅ Passed The PR directly addresses issue #237 by ensuring the exporter notifies the controller to release a lease when it times out without client connection, even with hooks configured.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the lease release issue when hooks are configured; no unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@python/packages/jumpstarter/jumpstarter/exporter/exporter.py`:
- Line 625: The guard that skips sending the release RPC when
lease_ended.is_set() causes controller-initiated lease ends to never send the
RPC; update _request_lease_release to accept an optional force: bool parameter
(default False) and only skip when lease_ended.is_set() && !force, then call it
with force=True from the controller-managed path where cleanup runs (e.g., from
_cleanup_after_lease and from run_after_lease_hook / request_lease_release in
hooks.py) so the RPC is sent even if lease_ended was already set; alternatively,
if you prefer ordering, move the call to _request_lease_release() to occur
before lease_ended.set() in serve()’s controller branch, but do one of these
changes so the release RPC is guaranteed to be sent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 976d3d4e-82a4-4fb4-93df-6c3cd6553189

📥 Commits

Reviewing files that changed from the base of the PR and between f92ac89 and 1fcdcef.

📒 Files selected for processing (2)
  • python/packages/jumpstarter/jumpstarter/exporter/exporter.py
  • python/packages/jumpstarter/jumpstarter/exporter/exporter_test.py

Comment thread python/packages/jumpstarter/jumpstarter/exporter/exporter.py
When a lease times out without any client connection and hooks are
configured, _cleanup_after_lease skipped the afterLease hook (correct)
but also skipped calling _request_lease_release (bug). This left the
exporter permanently stuck in LeaseReady status because the controller
was never notified that the lease should be freed.

Add _request_lease_release() call in the else branch of
_cleanup_after_lease so the controller always frees the lease,
regardless of whether the afterLease hook ran.

Fixes: jumpstarter-dev#237
Generated-By: Forge/20260416_202053_681470_86fec9bd_i237

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hooks enabled: exporter denial of service if letting an unused lease to timeout

1 participant