service

package
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 11, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Service

type Service struct {
	// contains filtered or unexported fields
}

func New

func New(cfg config.Config, logger *slog.Logger, db *store.Store, runtimeDriver runtime.Runtime, eventsClient *docker.Client, caddyClient *caddy.Client, cipher *secrets.Cipher, mountManager *mounts.Manager, admitter *capacity.Admitter) *Service

func (*Service) Capacity

func (s *Service) Capacity() capacity.Snapshot

Capacity returns the admitter's current snapshot. Returns the zero value when no admitter is configured (e.g. in tests).

func (*Service) CreateSandbox

func (*Service) DestroySandbox

func (s *Service) DestroySandbox(ctx context.Context, id string) error

func (*Service) EnsureLayer4Ready added in v0.1.4

func (s *Service) EnsureLayer4Ready(ctx context.Context) error

EnsureLayer4Ready bootstraps the caddy-l4 app under a single-flight mutex and latches success. Safe to call from boot AND from each L4 exposure path: the atomic fast-path turns it into a single load on the steady state, and a failed boot is recovered by the very next TCP/TLS expose call instead of surfacing as a confusing "layer4 app missing" error from caddy.

func (*Service) ExposePort

func (s *Service) ExposePort(ctx context.Context, id string, port int, protocol string) (models.ExposePortResponse, error)

ExposePort publishes a sandbox container port through one of three caddy surfaces, selected by protocol:

  • "" / "http": existing Caddy HTTP reverse-proxy route, returns https://<id>-<port>.<domain> (or the path-mode equivalent).
  • "tcp": allocates a parent-host TCP port from the [SB_L4_PORT_RANGE_START, SB_L4_PORT_RANGE_END] pool, points caddy-l4 at it, and returns tcp://<public-host>:<host-port>. This is what unblocks native Postgres / Redis / MySQL DSNs in the spawn-postgres docs.
  • "tls": adds a TLS-SNI route to the shared layer4 server. Requires --domain (so the SNI hostname has a place to resolve) and a non-empty SB_L4_TLS_LISTEN. Returns tls://<id>-<port>.<domain>:<l4-port>.

func (*Service) GetSandbox

func (s *Service) GetSandbox(ctx context.Context, id string) (*models.Sandbox, error)

func (*Service) Health

func (s *Service) Health(ctx context.Context) (models.HealthStatus, error)

func (*Service) ListMounts

func (s *Service) ListMounts(ctx context.Context, sandboxID string) ([]models.MountSpecRedacted, error)

ListMounts returns the redacted mount config for a sandbox. Credentials are never included in the response — they are write-only via CreateSandbox.

func (*Service) ListSandboxes

func (s *Service) ListSandboxes(ctx context.Context) ([]*models.Sandbox, error)

func (*Service) Reconcile

func (s *Service) Reconcile(ctx context.Context) error

func (*Service) ReplayReservations

func (s *Service) ReplayReservations(ctx context.Context)

ReplayReservations re-populates the admitter from persistent state. Without this, after a daemon restart the admitter sees zero reservations and the host can be overcommitted on the first wave of new sandboxes. Destroyed AND stopped sandboxes are skipped — neither holds host CPU/RAM (the stop path releases the slot, and StartSandbox re-Admits on the way back up), so counting them here would re-introduce the overcommit-budget bug we fixed when stop began releasing capacity. Best-effort: a store error is logged, not returned, since admission control degrading to "unaware" is preferable to refusing to boot.

func (*Service) ResizeSandbox

func (s *Service) ResizeSandbox(ctx context.Context, id string, req models.ResizeSandboxRequest) (*models.Sandbox, error)

func (*Service) StartEventMonitor

func (s *Service) StartEventMonitor(ctx context.Context)

StartEventMonitor launches the Docker event consumer goroutine. It is the realtime counterpart to Reconcile() — when a container dies, OOM-kills, or is destroyed out-of-band, this loop updates the DB and tears down routes within ~1s instead of waiting for the next reconcile tick.

func (*Service) StartLifecycleSweep

func (s *Service) StartLifecycleSweep(ctx context.Context)

StartLifecycleSweep launches the per-sandbox lifecycle ticker. Every minute it evaluates each sandbox's Lifecycle timers (StopIfIdleFor / DestroyIfIdleFor / StopAtAge / DestroyAtAge) plus the legacy global SB_IDLE_TIMEOUT_MIN fallback for sandboxes that don't declare any per-sandbox timers. Without either configured, the sweep still runs but is a no-op — kept on so a later UpdateLifecycle call doesn't need to start a goroutine.

func (*Service) StartReconcileLoop

func (s *Service) StartReconcileLoop(ctx context.Context)

func (*Service) StartSandbox

func (s *Service) StartSandbox(ctx context.Context, id string) (*models.Sandbox, error)

func (*Service) StopSandbox

func (s *Service) StopSandbox(ctx context.Context, id string) (*models.Sandbox, error)

func (*Service) ToolboxTarget

func (s *Service) ToolboxTarget(ctx context.Context, id string) (ToolboxEndpoint, error)

func (*Service) TouchSandbox

func (s *Service) TouchSandbox(ctx context.Context, id string) error

func (*Service) UnexposePort

func (s *Service) UnexposePort(ctx context.Context, id string, port int) error

func (*Service) UpdateLifecycle

func (s *Service) UpdateLifecycle(ctx context.Context, id string, l models.Lifecycle) (*models.Sandbox, error)

UpdateLifecycle replaces the lifecycle timers on an existing sandbox. Full-replacement semantics: pass zero in any field to clear that timer. The sweep picks up the new values on its next tick (within ~1 minute), so a tightened deadline can fire as soon as the next sweep runs.

type ToolboxEndpoint

type ToolboxEndpoint struct {
	URL   string
	Token string
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL