feat: stateful workspaces (suspend / resume across daemon restarts) — closes #116#122
Merged
Conversation
…nd/resume Stateful workspace MVP for #116. New types in api.rs: - WorkspaceStatus (Running / Suspended / Stale) - CreateWorkspaceRequest { name, snapshot_tag, per_child_netns, memory_limit_mib } - WorkspaceInfo { id, name, source_snapshot_tag, current_state_tag, status, live_sandbox_id, created_at_unix, last_active_unix, last_branch_memory_path } - SuspendWorkspaceRequest { diff: bool } Registry gains BTreeMap<String, WorkspaceInfo> keyed by name + list/get/insert/remove/update methods. reconcile() now also marks Running workspaces Stale at daemon startup if their live_sandbox_id no longer corresponds to a tracked sandbox. HTTP routes: - GET /v1/workspaces - POST /v1/workspaces — create + spawn first sandbox - GET /v1/workspaces/:name - DELETE /v1/workspaces/:name — kill sandbox + drop state snapshot - POST /v1/workspaces/:name/suspend — branch live sandbox to ws-<name>-state, kill sandbox - POST /v1/workspaces/:name/resume — spawn from current_state_tag (or source if first resume) State-tag scheme is overwrite-on-suspend (ws-<name>-state), bounded to one snapshot per workspace on disk. Source snapshot is preserved on delete; only the workspace's own state snapshot is removed. Suspend respects v0.3 diff: true and the previous-output chain via last_branch_memory_path persisted on WorkspaceInfo. CLI subcommands + tests land in a follow-up commit on this branch. Refs #116. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wraps the new daemon workspace API in CLI subcommands. Driver uses ureq (already in the cli crate) to hit the daemon's REST endpoints. Subcommands: - create <name> --snapshot <tag> [--per-child-netns] [--memory-limit-mib N] - suspend <name> [--diff] - resume <name> - list - delete <name> All accept --daemon-url (env FORKD_URL) and --daemon-token (env FORKD_TOKEN), matching the existing snapshot subcommand conventions. Refs #116. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #116 (item 4 of meta #112). Stickiness track — Daytona's killer feature, ported to forkd.
What
A workspace is a long-lived sandbox tracked by name. Users can
suspendit (snapshot the live VM, kill the firecracker, retain the state on disk) andresumeit later — even across daemon restarts.API
CLI
Smoke test (verified end-to-end on dev box)
Design choices
ws-<name>-state), bounded to one snapshot per workspace on disk.last_branch_memory_pathacross the workspace lifetime so successivesuspend --diffcalls chain off the previous one (just like multi-BRANCH on a sandbox).reconcile()flips Running workspaces to Stale (live sandbox gone after restart). User runsresumemanually to bring them back fromcurrent_state_tag.Out of scope (follow-ups)