ExDaytona.Snapshot (ex_daytona v0.4.0)

Copy Markdown View Source

Prebuilt sandbox snapshots: build once, create sandboxes instantly.

Building a sandbox from an ExDaytona.Image runs the Docker build on every create. The fast production pattern is to build a snapshot from the image once and create every sandbox from it:

image =
  ExDaytona.Image.from("ubuntu:22.04")
  |> ExDaytona.Image.run("apt-get update && apt-get install -y curl git")

{:ok, snapshot} =
  ExDaytona.Snapshot.build(client, "my-app-base", image, log: &IO.write/1)

# From here on, creation skips the build entirely:
{:ok, sandbox} = ExDaytona.Sandbox.create(client, snapshot: "my-app-base")

Snapshots can also wrap a registry image (image_name:) instead of a declarative build, and can be deactivated/reactivated to manage the organization's snapshot quota (ExDaytona.Quota.overview/2 reports usage). For pre-warmed running sandboxes on top of a snapshot, see ExDaytona.WarmPool.

Summary

Functions

Reactivate a deactivated snapshot. Returns the updated ExDaytona.Model.SnapshotDto.

Poll until the snapshot reaches state (a string or list of strings, e.g. "active").

Build a snapshot from an image and wait for it to become activecreate/3 with the image required and optional live build-log streaming

The snapshot's build logs so far, as a binary. Only snapshots created from build info have build logs.

Create a snapshot named name and (by default) wait for it to become active.

Deactivate a snapshot (it stops counting toward active usage; sandboxes can no longer be created from it until reactivated). Returns :ok.

Delete a snapshot by id. Returns :ok.

Fetch a snapshot by id or name as an ExDaytona.Model.SnapshotDto.

List snapshots. Accepts :page, :limit, :name (partial match), :source_sandbox_id, :sort, :order; returns {:ok, %{items: [%ExDaytona.Model.SnapshotDto{}], page: n, total: n, total_pages: n}}.

Follow the snapshot's build logs in real time: fun is invoked with each chunk as it is produced, and the call returns :ok when the build finishes and the stream closes.

Functions

activate(client, snapshot_id)

@spec activate(ExDaytona.Client.t(), String.t()) ::
  {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}

Reactivate a deactivated snapshot. Returns the updated ExDaytona.Model.SnapshotDto.

await_state(client, snapshot_id, state, opts \\ [])

@spec await_state(
  ExDaytona.Client.t(),
  String.t(),
  String.t() | [String.t()],
  keyword()
) ::
  {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}

Poll until the snapshot reaches state (a string or list of strings, e.g. "active").

Fails fast with {:error, %Error{}} when the snapshot enters an error state (["error", "build_failed"], with the provider's errorReason in the message), and with a timeout error after :timeout milliseconds (default 300_000; poll interval :poll_interval, default 2_000).

build(client, name, image, opts \\ [])

Build a snapshot from an image and wait for it to become activecreate/3 with the image required and optional live build-log streaming:

{:ok, snapshot} =
  ExDaytona.Snapshot.build(client, "my-app-base", image,
    log: &IO.write/1,
    timeout: 600_000
  )

Options

  • :log — a fun invoked with each build-log chunk while the build runs (streamed concurrently via stream_build_logs/4)
  • everything create/3 accepts except :image/:wait (build always waits — a snapshot is only useful active)

build_logs(client, snapshot_id)

@spec build_logs(ExDaytona.Client.t(), String.t()) ::
  {:ok, binary()} | {:error, ExDaytona.Error.t()}

The snapshot's build logs so far, as a binary. Only snapshots created from build info have build logs.

create(client, name, opts \\ [])

@spec create(ExDaytona.Client.t(), String.t(), keyword()) ::
  {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}

Create a snapshot named name and (by default) wait for it to become active.

Options

  • :image — build declaratively: an ExDaytona.Image or a raw Dockerfile string (local build contexts are uploaded automatically, as in ExDaytona.Sandbox.create/2)
  • :image_name — wrap an existing registry image instead of building
  • :wait — wait until the snapshot is active (default true)
  • :timeout — max milliseconds to wait (default 300_000 — builds take longer than sandbox starts)
  • :poll_interval — milliseconds between state polls (default 2_000)
  • snapshot settings, all optional: :entrypoint (list), :cpu, :memory, :disk, :gpu, :gpu_type, :region_id, :sandbox_class

Returns {:ok, %ExDaytona.Model.SnapshotDto{}}. Watch a build in progress with stream_build_logs/4, or use build/4 to do both in one call.

deactivate(client, snapshot_id)

@spec deactivate(ExDaytona.Client.t(), String.t()) ::
  :ok | {:error, ExDaytona.Error.t()}

Deactivate a snapshot (it stops counting toward active usage; sandboxes can no longer be created from it until reactivated). Returns :ok.

delete(client, snapshot_id)

@spec delete(ExDaytona.Client.t(), String.t()) :: :ok | {:error, ExDaytona.Error.t()}

Delete a snapshot by id. Returns :ok.

get(client, id_or_name)

Fetch a snapshot by id or name as an ExDaytona.Model.SnapshotDto.

list(client, opts \\ [])

@spec list(
  ExDaytona.Client.t(),
  keyword()
) ::
  {:ok,
   %{
     items: [ExDaytona.Model.SnapshotDto.t()],
     page: number() | nil,
     total: number() | nil,
     total_pages: number() | nil
   }}
  | {:error, ExDaytona.Error.t()}

List snapshots. Accepts :page, :limit, :name (partial match), :source_sandbox_id, :sort, :order; returns {:ok, %{items: [%ExDaytona.Model.SnapshotDto{}], page: n, total: n, total_pages: n}}.

stream_build_logs(client, snapshot_id, fun, opts \\ [])

@spec stream_build_logs(
  ExDaytona.Client.t(),
  String.t(),
  (binary() -> any()),
  keyword()
) ::
  :ok | {:error, ExDaytona.Error.t()}

Follow the snapshot's build logs in real time: fun is invoked with each chunk as it is produced, and the call returns :ok when the build finishes and the stream closes.

Options: :timeout — max milliseconds to wait between chunks (default :infinity); :deadline — overall milliseconds for the stream.