Skip to content

Commit cad4ed3

Browse files
committed
fix(server): clean sandbox-owned records on reconcile delete
1 parent 70dc281 commit cad4ed3

1 file changed

Lines changed: 92 additions & 30 deletions

File tree

  • crates/openshell-server/src/compute

crates/openshell-server/src/compute/mod.rs

Lines changed: 92 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -480,36 +480,7 @@ impl ComputeRuntime {
480480
.map_err(|e| Status::internal(format!("persist sandbox failed: {e}")))?;
481481
self.sandbox_index.update_from_sandbox(&sandbox);
482482
self.sandbox_watch_bus.notify(&id);
483-
484-
if let Ok(records) = self.store.list(SshSession::object_type(), 1000, 0).await {
485-
for record in records {
486-
if let Ok(session) = SshSession::decode(record.payload.as_slice())
487-
&& session.sandbox_id == id
488-
&& let Err(e) = self
489-
.store
490-
.delete(SshSession::object_type(), session.object_id())
491-
.await
492-
{
493-
warn!(
494-
session_id = %session.object_id(),
495-
error = %e,
496-
"Failed to delete SSH session during sandbox cleanup"
497-
);
498-
}
499-
}
500-
}
501-
502-
if let Err(e) = self
503-
.store
504-
.delete_by_name(SANDBOX_SETTINGS_OBJECT_TYPE, sandbox.object_name())
505-
.await
506-
{
507-
warn!(
508-
sandbox_id = %id,
509-
error = %e,
510-
"Failed to delete sandbox settings during cleanup"
511-
);
512-
}
483+
self.cleanup_sandbox_owned_records(&sandbox).await;
513484

514485
let driver_sandbox = driver_sandbox_from_public(&sandbox);
515486
let deleted = self
@@ -959,6 +930,15 @@ impl ComputeRuntime {
959930
}
960931

961932
async fn apply_deleted_locked(&self, sandbox_id: &str) -> Result<(), String> {
933+
let sandbox = self
934+
.store
935+
.get_message::<Sandbox>(sandbox_id)
936+
.await
937+
.map_err(|e| e.to_string())?;
938+
if let Some(sandbox) = sandbox.as_ref() {
939+
self.cleanup_sandbox_owned_records(sandbox).await;
940+
}
941+
962942
let _ = self
963943
.store
964944
.delete(Sandbox::object_type(), sandbox_id)
@@ -970,6 +950,44 @@ impl ComputeRuntime {
970950
Ok(())
971951
}
972952

953+
async fn cleanup_sandbox_owned_records(&self, sandbox: &Sandbox) {
954+
self.cleanup_sandbox_ssh_sessions(sandbox.object_id()).await;
955+
956+
if let Err(e) = self
957+
.store
958+
.delete_by_name(SANDBOX_SETTINGS_OBJECT_TYPE, sandbox.object_name())
959+
.await
960+
{
961+
warn!(
962+
sandbox_id = %sandbox.object_id(),
963+
sandbox_name = %sandbox.object_name(),
964+
error = %e,
965+
"Failed to delete sandbox settings during cleanup"
966+
);
967+
}
968+
}
969+
970+
async fn cleanup_sandbox_ssh_sessions(&self, sandbox_id: &str) {
971+
if let Ok(records) = self.store.list(SshSession::object_type(), 1000, 0).await {
972+
for record in records {
973+
if let Ok(session) = SshSession::decode(record.payload.as_slice())
974+
&& session.sandbox_id == sandbox_id
975+
&& let Err(e) = self
976+
.store
977+
.delete(SshSession::object_type(), session.object_id())
978+
.await
979+
{
980+
warn!(
981+
sandbox_id = %sandbox_id,
982+
session_id = %session.object_id(),
983+
error = %e,
984+
"Failed to delete SSH session during sandbox cleanup"
985+
);
986+
}
987+
}
988+
}
989+
}
990+
973991
fn cleanup_sandbox_state(&self, sandbox_id: &str) {
974992
self.tracing_log_bus.remove(sandbox_id);
975993
self.tracing_log_bus.platform_event_bus.remove(sandbox_id);
@@ -1776,6 +1794,21 @@ mod tests {
17761794
}
17771795
}
17781796

1797+
fn ssh_session_record(id: &str, sandbox_id: &str) -> SshSession {
1798+
SshSession {
1799+
metadata: Some(openshell_core::proto::datamodel::v1::ObjectMeta {
1800+
id: id.to_string(),
1801+
name: format!("session-{id}"),
1802+
created_at_ms: 1000000,
1803+
labels: std::collections::HashMap::new(),
1804+
}),
1805+
sandbox_id: sandbox_id.to_string(),
1806+
token: format!("token-{id}"),
1807+
revoked: false,
1808+
expires_at_ms: 0,
1809+
}
1810+
}
1811+
17791812
fn make_driver_condition(reason: &str, message: &str) -> DriverCondition {
17801813
DriverCondition {
17811814
r#type: "Ready".to_string(),
@@ -2427,6 +2460,19 @@ mod tests {
24272460
let sandbox = sandbox_record("sb-1", "sandbox-a", SandboxPhase::Provisioning);
24282461
runtime.store.put_message(&sandbox).await.unwrap();
24292462
runtime.sandbox_index.update_from_sandbox(&sandbox);
2463+
runtime
2464+
.store
2465+
.put(
2466+
SANDBOX_SETTINGS_OBJECT_TYPE,
2467+
"settings-sb-1",
2468+
sandbox.object_name(),
2469+
br#"{"revision":1,"settings":{}}"#,
2470+
None,
2471+
)
2472+
.await
2473+
.unwrap();
2474+
let session = ssh_session_record("session-1", sandbox.object_id());
2475+
runtime.store.put_message(&session).await.unwrap();
24302476

24312477
let mut watch_rx = runtime.sandbox_watch_bus.subscribe(sandbox.object_id());
24322478

@@ -2449,6 +2495,22 @@ mod tests {
24492495
.sandbox_id_for_sandbox_name(sandbox.object_name())
24502496
.is_none()
24512497
);
2498+
assert!(
2499+
runtime
2500+
.store
2501+
.get_by_name(SANDBOX_SETTINGS_OBJECT_TYPE, sandbox.object_name())
2502+
.await
2503+
.unwrap()
2504+
.is_none()
2505+
);
2506+
assert!(
2507+
runtime
2508+
.store
2509+
.get_message::<SshSession>(session.object_id())
2510+
.await
2511+
.unwrap()
2512+
.is_none()
2513+
);
24522514
let _ = watch_rx.try_recv();
24532515
assert!(matches!(
24542516
watch_rx.try_recv(),

0 commit comments

Comments
 (0)