@@ -368,6 +368,45 @@ const collectArtifactsOnStop = (
368368 ) ,
369369 )
370370
371+ const finalizeSandboxStop = (
372+ sandboxId : string ,
373+ idBytes : Uint8Array ,
374+ orgId : string ,
375+ actorId : string ,
376+ ) =>
377+ Effect . gen ( function * ( ) {
378+ // Collect artifacts before fully stopping (best-effort)
379+ yield * collectArtifactsOnStop ( sandboxId , idBytes , orgId )
380+
381+ // Tell the node daemon to stop the VM (best-effort)
382+ const nodeClient = yield * NodeClient
383+ yield * nodeClient . stopSandbox ( { sandboxId : idBytes } ) . pipe (
384+ Effect . catchAll ( ( ) => Effect . void ) ,
385+ )
386+
387+ // Transition to stopped
388+ yield * SandboxRepo . pipe (
389+ Effect . flatMap ( ( repo ) =>
390+ repo . updateStatus ( idBytes , orgId , 'stopped' , {
391+ endedAt : new Date ( ) ,
392+ } ) ,
393+ ) ,
394+ )
395+
396+ const auditLog = yield * AuditLog
397+ yield * auditLog . append ( {
398+ orgId,
399+ actorId,
400+ action : 'sandbox.stop' ,
401+ resourceType : 'sandbox' ,
402+ resourceId : sandboxId ,
403+ } )
404+ } ) . pipe (
405+ Effect . catchAllCause ( ( cause ) =>
406+ Effect . logError ( `Sandbox stop finalization failed for ${ sandboxId } : ${ Cause . pretty ( cause ) } ` ) ,
407+ ) ,
408+ )
409+
371410const stopSandbox = Effect . gen ( function * ( ) {
372411 yield * requireScope ( 'sandbox:write' )
373412 const auth = yield * AuthContext
@@ -417,32 +456,11 @@ const stopSandbox = Effect.gen(function* () {
417456 failureReason : 'sandbox_stopped' ,
418457 } )
419458
420- // Collect artifacts before fully stopping (best-effort)
421- yield * collectArtifactsOnStop ( id , idBytes , auth . orgId )
422-
423- // Tell the node daemon to stop the VM (best-effort)
424- const nodeClient = yield * NodeClient
425- yield * nodeClient . stopSandbox ( { sandboxId : idBytes } ) . pipe (
426- Effect . catchAll ( ( ) => Effect . void ) ,
427- )
428-
429- // Transition to stopped
430- const stopped = yield * repo . updateStatus ( idBytes , auth . orgId , 'stopped' , {
431- endedAt : new Date ( ) ,
432- } )
433-
434- const auditLog = yield * AuditLog
435- yield * auditLog . append ( {
436- orgId : auth . orgId ,
437- actorId : auth . userId ,
438- action : 'sandbox.stop' ,
439- resourceType : 'sandbox' ,
440- resourceId : id ,
441- } )
459+ yield * Effect . forkDaemon ( finalizeSandboxStop ( id , idBytes , auth . orgId , auth . userId ) )
442460
443461 const response : StopSandboxResponse = {
444462 sandbox_id : id ,
445- status : stopped ?. status ?? 'stopped ',
463+ status : 'stopping ',
446464 }
447465
448466 return HttpServerResponse . unsafeJson ( response , { status : 202 } )
0 commit comments