Skip to content

[Feat] Enable environment and task snapshot resume on Daytona - #167

Merged
mrubens merged 2 commits into
developfrom
feature/daytona-snapshot-parity-1ybi1knt9s5ko
Jul 11, 2026
Merged

[Feat] Enable environment and task snapshot resume on Daytona#167
mrubens merged 2 commits into
developfrom
feature/daytona-snapshot-parity-1ybi1knt9s5ko

Conversation

@roomote-roomote

Copy link
Copy Markdown
Contributor

Opened on behalf of Matt Rubens. Follow up by mentioning @openmote, in the web UI, or in Slack.

Related issue

N/A — internal Roomote work requested in Slack after reviewing Daytona pause/fork / Snapshot product gaps.

Why this PR exists

  • A maintainer explicitly invited this PR in the linked issue or discussion
  • I am a maintainer / this is internal Roomote work

What changed

Enable Daytona for Roomote’s product snapshot flows (environment setup snapshots and task sleep/resume), using durable named filesystem snapshots like Modal and E2B rather than pause-in-place.

  • Implement DaytonaClient.createSnapshot via _experimental_createSnapshot (name as snapshotId, destroy source sandbox afterward)
  • Implement resumeFromSnapshot by creating a sandbox from that named snapshot
  • Extend createDaytonaMachine / spawn-daytona-worker for fresh / environment_snapshot / task_snapshot launch modes (mirrors E2B)
  • Mark Daytona snapshot/resume capable in types + setup catalog so sleep-check auto-snapshots resumable runs
  • Keep DAYTONA_SNAPSHOT_NAME as the worker base image only; product snaps use roomote-run-snap-*
  • Docs distinguish worker base snapshots vs product snapshots

How it was tested

  • pnpm --filter @roomote/compute-providers exec vitest run src/__tests__/adapters.contract.test.ts (create + resume + destroy after snapshot)
  • pnpm lint && pnpm check-types
  • pnpm --filter @roomote/docs check
  • No live Daytona API spike in this environment (experimental API path is unit-tested with mocks)

Checklist

  • The PR title follows the repo convention: [Fix], [Feat], [Improve], [Refactor], [Docs], or [Chore] followed by a user-facing description
  • This PR is small and scoped to one change
  • pnpm lint and pnpm check-types pass locally
  • I added tests or included a clear manual validation note above
  • I removed secrets, tokens, private keys, and customer data from code, logs, and screenshots
  • If this change should appear in the changelog, I ran pnpm changeset

Wire Daytona createSnapshot/resumeFromSnapshot via durable named
filesystem snapshots, thin emit capabilities, and mirror E2B launch
modes for environment and task resumes.
@roomote-roomote

roomote-roomote Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

No new code issues found. The earlier comment nit is now fixed. See task

  • apps/bullmq/src/scheduled-jobs/sleep-check.ts:156-159 — Stale comment: the isSnapshotResumableSleepCandidate JSDoc still said "Non-snapshot providers (Daytona) always fall through to the destroy paths." Fixed in 909ce31: the JSDoc now cites Docker as the non-snapshot example and lists Modal, E2B, and Daytona as snapshot-capable, matching snapshotCapableComputeProviders.

Summary

This enables Daytona for Roomote's snapshot/resume flows by porting the E2B model (durable named filesystem snapshots + fresh/environment_snapshot/task_snapshot launch modes). I verified:

  • spawnDaytonaWorker is essentially line-for-line equivalent to spawnE2bWorker, including launch-mode selection, the SnapshotResume missing-sourceSnapshotId guard, and worker command/args.
  • createDaytonaMachine's shouldInstallShippedRuntime = launchMode !== 'task_snapshot' and the task_snapshot early-return match createE2bMachine.
  • _experimental_createSnapshot(name, timeout?) and getPreviewLink(port) match the installed @daytonaio/sdk@0.190.1 types.
  • createSnapshot destroying the source sandbox after capture matches Modal's snapshot-kills-sandbox contract, and the snapshot BullMQ job + sleep-check already build a Daytona client whose snapshotName resolves from DAYTONA_SNAPSHOT_NAME.
  • reconcileSnapshottingFailure gracefully handles Daytona not implementing the optional findSnapshotBySourceInstance.
  • snapshotCapableComputeProviders now includes daytona, and sleepCheckManagedComputeProviders (spread) resolves to the same {modal, e2b, daytona} set as before.

Sync update (head 909ce31): The only change since the prior review is the docs fix above, which resolves the single outstanding checklist item. No new code issues.

Non-blocking note (low confidence): Because createSnapshot derives a new random snapshot name per call, destroys the source sandbox, and Daytona has no findSnapshotBySourceInstance reconcile, each sleep/resume cycle leaves the previous named snapshot orphaned, and a partial failure after a snapshot completes server-side but before DB persistence cannot be recovered (the run is marked failed instead). This mirrors accepted cross-provider snapshot behavior and DB-level expiry (SANDBOX_SNAPSHOT_EXPIRY_MS), so it may be intentional — worth confirming whether orphaned Daytona named snapshots get garbage-collected.

Daytona is snapshot-capable; update the comment so destroy-path wording
only describes non-snapshot providers.
@mrubens
mrubens marked this pull request as ready for review July 11, 2026 05:17
@mrubens
mrubens merged commit d1ca66f into develop Jul 11, 2026
1 check passed
@mrubens
mrubens deleted the feature/daytona-snapshot-parity-1ybi1knt9s5ko branch July 11, 2026 06:04
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.

1 participant