Skip to content

fix(server): prevent unbounded bus entry growth for sandbox IDs#138

Merged
johntmyers merged 1 commit intomainfrom
fix/27-unbounded-watchsandbox-bus-cleanup/jomyers
Mar 5, 2026
Merged

fix(server): prevent unbounded bus entry growth for sandbox IDs#138
johntmyers merged 1 commit intomainfrom
fix/27-unbounded-watchsandbox-bus-cleanup/jomyers

Conversation

@johntmyers
Copy link
Collaborator

🏗️ build-from-issue-agent

Closes #27

Summary

Prevents unbounded memory growth caused by sandbox bus entries (TracingLogBus, PlatformEventBus, SandboxWatchBus) that were never cleaned up when sandboxes were deleted. Additionally, WatchSandbox now validates sandbox existence before subscribing to buses (preventing entries for non-existent IDs), and PushSandboxLogs validates sandbox existence once at stream open.

Changes Made

  • crates/navigator-server/src/tracing_bus.rs: Added remove() method to TracingLogBus (cleans up per_id and tails maps) and remove() method to PlatformEventBus. Added 7 unit tests.
  • crates/navigator-server/src/sandbox_watch.rs: Added remove() method to SandboxWatchBus. Added 3 unit tests.
  • crates/navigator-server/src/sandbox/mod.rs: Wired bus cleanup into handle_deleted reconciler — calls remove() on all three buses after sandbox deletion. Updated spawn_sandbox_watcher to accept TracingLogBus parameter.
  • crates/navigator-server/src/grpc.rs: Wired bus cleanup into delete_sandbox gRPC handler. Reordered watch_sandbox to validate sandbox existence before subscribing to buses (validate → subscribe → re-read snapshot). Added one-time sandbox validation at stream open in push_sandbox_logs.
  • crates/navigator-server/src/lib.rs: Pass tracing_log_bus to spawn_sandbox_watcher.
  • architecture/gateway.md: Documented bus cleanup and validation behavior.

Deviations from Plan

None — implemented as planned.

Tests Added

  • Unit: 10 tests added across tracing_bus.rs (7 tests: remove cleans up maps, subscribe after remove creates fresh channel, remove closes active receivers, remove nonexistent is noop — for both TracingLogBus and PlatformEventBus) and sandbox_watch.rs (3 tests: remove cleans up, subscribe after remove creates fresh channel, remove nonexistent is noop)
  • Integration: N/A
  • E2E: N/A

Documentation Updated

  • architecture/gateway.md: Added cleanup and validation notes to the bus section

Verification

  • Pre-commit checks passing (license:check failure is pre-existing on main for tmp/network_checks.py)
  • All 70 navigator-server tests passing (65 existing + 10 new, plus 5 integration)
  • E2E tests (not applicable — no e2e/ changes)
  • Architecture documentation updated

Closes #27

Add remove() methods to TracingLogBus, PlatformEventBus, and
SandboxWatchBus to clean up entries when sandboxes are deleted.
Wire cleanup into both handle_deleted (K8s reconciler) and
delete_sandbox (gRPC handler). Reorder watch_sandbox to validate
sandbox existence before subscribing to buses, preventing entries
for non-existent IDs. Add one-time sandbox validation at stream
open in push_sandbox_logs.
@johntmyers johntmyers self-assigned this Mar 5, 2026
@johntmyers johntmyers merged commit e8e81a3 into main Mar 5, 2026
10 checks passed
@johntmyers johntmyers deleted the fix/27-unbounded-watchsandbox-bus-cleanup/jomyers branch March 5, 2026 23:58
drew pushed a commit that referenced this pull request Mar 16, 2026
Closes #27

Add remove() methods to TracingLogBus, PlatformEventBus, and
SandboxWatchBus to clean up entries when sandboxes are deleted.
Wire cleanup into both handle_deleted (K8s reconciler) and
delete_sandbox (gRPC handler). Reorder watch_sandbox to validate
sandbox existence before subscribing to buses, preventing entries
for non-existent IDs. Add one-time sandbox validation at stream
open in push_sandbox_logs.

Co-authored-by: John Myers <johntmyers@users.noreply.github.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.

Unbounded WatchSandbox sandbox_id

1 participant