sessions

package
v0.7.23 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package sessions implements long-running command sessions inside a sandbox container: PTY or pipes, in-memory replay buffer, fan-out to multiple attached clients, and asciinema recording. Designed to live in toolboxd (PID 1 of the container) and be reachable via the toolbox HTTP/WS API.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("session not found")

ErrNotFound is returned when a session ID isn't tracked.

Functions

This section is empty.

Types

type Config

type Config struct {
	// SandboxID is recorded in metadata and used as a recordings subdirectory.
	SandboxID string
	// RecordingDir is where asciinema cast files land. Required.
	RecordingDir string
	// RecordingRetention prunes cast files older than this. Zero = never.
	RecordingRetention time.Duration
	// SweepInterval drives the retention sweeper. Default 1 h.
	SweepInterval time.Duration
	// BufferBytes is the per-session replay buffer size. Default 1 MiB.
	BufferBytes int
}

Config controls Manager behavior. Defaults are sensible for an in-container daemon; everything is overridable via toolboxd env vars.

type Frame

type Frame struct {
	Stream Stream
	Data   []byte
}

Frame is a unit of session output observed by an attached client.

type Manager

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

Manager owns every Session running in the container.

func New

func New(logger *slog.Logger, cfg Config) (*Manager, error)

New constructs a Manager and starts its retention sweeper.

func (*Manager) Close

func (m *Manager) Close()

Close kills every running session and stops the sweeper. Best-effort.

func (*Manager) Create

Create starts a new session. Always assigns a fresh ID.

func (*Manager) Delete

func (m *Manager) Delete(id string) error

Delete removes a session record. If it's still running, signal it first. Always best-effort — does not block on the process actually exiting.

func (*Manager) FlushRecording added in v0.4.1

func (m *Manager) FlushRecording(id string) error

FlushRecording best-effort fsyncs the asciinema cast file for the given session id. Called from the in-guest vsock handler's OnPreSnapshot (Phase 3 PR-B) so a clone resumed from the snapshot observes a session recording that ends cleanly at the freeze point rather than missing the trailing few-hundred bytes. Returns nil for sessions without an attached recording (the common case for template captures), unknown IDs (caller iterates List() and a session can finish between the two calls), and recorders that have already been Close()d.

func (*Manager) Get

func (m *Manager) Get(id string) (*Session, error)

Get fetches a session by ID. Returns ErrNotFound if missing.

func (*Manager) GetByName added in v0.1.7

func (m *Manager) GetByName(name string) (*Session, error)

GetByName fetches a running session by its stable name. Exited sessions are not returned because the byName map is cleared when a session finishes.

func (*Manager) GetOrCreate

func (m *Manager) GetOrCreate(ctx context.Context, req models.CreateSessionRequest) (*Session, bool, error)

GetOrCreate returns the running session with the given Name (creating it from req if absent). Used by SSH attach so `ssh sandbox+default@host` idempotently lands on a single shared shell.

func (*Manager) List

func (m *Manager) List() []models.Session

List returns metadata for every session currently tracked, ordered by CreatedAt ascending.

type Session

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

Session is one long-running process plus the fan-out hub that distributes its output to attached clients. Methods are safe for concurrent use.

func (*Session) CloseStdin

func (s *Session) CloseStdin() error

CloseStdin half-closes stdin so the process sees EOF.

func (*Session) Done

func (s *Session) Done() <-chan struct{}

Done returns a channel that closes when the underlying process exits.

func (*Session) ExitInfo

func (s *Session) ExitInfo() (int, string)

ExitInfo returns the exit code and signal name (empty if not signaled). If the session is still running, returns -1, "".

func (*Session) ID

func (s *Session) ID() string

ID returns the session's stable identifier.

func (*Session) IsPTY

func (s *Session) IsPTY() bool

IsPTY reports whether the session was started in PTY mode.

func (*Session) Name

func (s *Session) Name() string

Name returns the human-friendly session name.

func (*Session) PID added in v0.1.7

func (s *Session) PID() int

PID returns the OS process identifier for the session, or 0 when the session has not started successfully.

func (*Session) RecordingPath

func (s *Session) RecordingPath() string

RecordingPath returns the absolute path to the session's asciinema cast file, or "" if recording is disabled.

func (*Session) Replay

func (s *Session) Replay() []byte

Replay returns the current contents of the replay buffer (oldest→newest).

func (*Session) Resize

func (s *Session) Resize(cols, rows int) error

Resize updates the PTY window size. No-op in pipe mode.

func (*Session) Signal

func (s *Session) Signal(name string) error

Signal sends a signal to the session's process group. Accepts INT, TERM, KILL, HUP, QUIT (with or without SIG prefix).

func (*Session) Snapshot

func (s *Session) Snapshot() models.Session

Snapshot returns the metadata view of the session.

func (*Session) Subscribe

func (s *Session) Subscribe() (<-chan Frame, func())

Subscribe registers a new attacher. The returned channel first receives a replay frame containing the current buffer contents (merged as stdout), then live output frames in order until the session ends or the caller calls the cancel function. Channel buffer size is 64; slow consumers drop older frames.

func (*Session) Write

func (s *Session) Write(p []byte) (int, error)

Write forwards bytes to the session's stdin (PTY in PTY mode, pipe stdin otherwise). Returns an error if the session has exited or stdin is closed.

type Stream

type Stream uint8

Stream identifies which output stream a chunk of bytes belongs to. Pipe mode uses both; PTY mode only uses Stdout.

const (
	StreamStdout Stream = 1
	StreamStderr Stream = 2
)

Jump to

Keyboard shortcuts

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