Documentation
¶
Index ¶
- Constants
- Variables
- type ClusterSecretRecord
- type ContainerNetnsPoolStats
- type ContainerNetnsSlot
- type CustomDomainRow
- type FirecrackerTapPoolStats
- type FirecrackerTapSlot
- type FirecrackerVMMPoolStats
- type FirecrackerVMMSlot
- type PendingImageGCEntry
- type ReserveHostPortResult
- type Store
- func (s *Store) AddCustomDomain(ctx context.Context, sandboxID, hostname string, targetPort int) error
- func (s *Store) AdoptContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) (*ContainerNetnsSlot, error)
- func (s *Store) AllocateFirecrackerTapSlot(ctx context.Context, sandboxID string, now time.Time) (*FirecrackerTapSlot, error)
- func (s *Store) AllocateFirecrackerVMMSlot(ctx context.Context, templateID, sandboxID string, now time.Time) (*FirecrackerVMMSlot, error)
- func (s *Store) BeginPrewarmContainerNetnsSlot(ctx context.Context, now time.Time) (*ContainerNetnsSlot, error)
- func (s *Store) ClaimIdempotentRequest(ctx context.Context, scope, fingerprint string, now time.Time, ...) (*models.IdempotentRequestRecord, bool, error)
- func (s *Store) ClaimPooledContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) (*ContainerNetnsSlot, error)
- func (s *Store) ClearNetworkQuotaExceeded(ctx context.Context, id string) error
- func (s *Store) Close() error
- func (s *Store) CompareCloneGeneration(ctx context.Context, sandboxID, snapshotGen string) error
- func (s *Store) CompleteIdempotentRequest(ctx context.Context, scope, fingerprint, targetID string, now time.Time, ...) error
- func (s *Store) CountVolumeAttachments(ctx context.Context, tenant, volumeID string) (int, error)
- func (s *Store) CountVolumes(ctx context.Context, tenant string) (int, error)
- func (s *Store) Create(ctx context.Context, sandbox *models.Sandbox) error
- func (s *Store) CreateSnapshot(ctx context.Context, snapshot *models.SandboxSnapshot) error
- func (s *Store) CreateTemplate(ctx context.Context, template *models.Template) error
- func (s *Store) CreateVolume(ctx context.Context, v *models.Volume) error
- func (s *Store) Delete(ctx context.Context, id string) error
- func (s *Store) DeleteAllWasmCheckpointPushes(ctx context.Context, sandboxID string) error
- func (s *Store) DeleteAllWasmStateKV(ctx context.Context, sandboxID string) error
- func (s *Store) DeleteClusterSecretsForSandbox(ctx context.Context, sandboxID string) error
- func (s *Store) DeleteFirecrackerVMMSlot(ctx context.Context, slotID string) error
- func (s *Store) DeleteIdempotentRequest(ctx context.Context, scope, fingerprint string) error
- func (s *Store) DeleteMounts(ctx context.Context, sandboxID string) error
- func (s *Store) DeletePendingImageGC(ctx context.Context, image string) error
- func (s *Store) DeletePendingImageGCIfScheduledAt(ctx context.Context, image string, at time.Time) (bool, error)
- func (s *Store) DeletePendingVolumeDeletion(ctx context.Context, volumeID string) error
- func (s *Store) DeletePort(ctx context.Context, sandboxID string, port int) error
- func (s *Store) DeleteSnapshot(ctx context.Context, name string) error
- func (s *Store) DeleteSnapshotAlias(ctx context.Context, alias string) error
- func (s *Store) DeleteTemplate(ctx context.Context, id string) error
- func (s *Store) DeleteVolume(ctx context.Context, tenant, id string) error
- func (s *Store) DeleteVolumeAttachmentsForSandbox(ctx context.Context, sandboxID string) error
- func (s *Store) DeleteVolumeIfUnattached(ctx context.Context, tenant, id, fallbackSource string) error
- func (s *Store) DeleteWasmCheckpointPush(ctx context.Context, id int64) error
- func (s *Store) DeleteWasmModule(ctx context.Context, id string) error
- func (s *Store) DeleteWasmStateKV(ctx context.Context, sandboxID, key string) error
- func (s *Store) FinishPrewarmContainerNetnsSlot(ctx context.Context, slotID, netnsPath, containerIP string, now time.Time) error
- func (s *Store) Get(ctx context.Context, id string) (*models.Sandbox, error)
- func (s *Store) GetClusterSecret(ctx context.Context, ref string) (*ClusterSecretRecord, error)
- func (s *Store) GetCompatState(ctx context.Context, sandboxID, facade string) (*models.SandboxCompatState, error)
- func (s *Store) GetContainerNetnsPoolStats(ctx context.Context) (ContainerNetnsPoolStats, error)
- func (s *Store) GetContainerNetnsSlotBySandbox(ctx context.Context, sandboxID string) (*ContainerNetnsSlot, error)
- func (s *Store) GetFirecrackerTapPoolStats(ctx context.Context) (FirecrackerTapPoolStats, error)
- func (s *Store) GetFirecrackerTapSlotBySandbox(ctx context.Context, sandboxID string) (*FirecrackerTapSlot, error)
- func (s *Store) GetFirecrackerVMMPoolStats(ctx context.Context, templateID string) (FirecrackerVMMPoolStats, error)
- func (s *Store) GetFirecrackerVMMSlotByID(ctx context.Context, slotID string) (*FirecrackerVMMSlot, error)
- func (s *Store) GetFirecrackerVMMSlotBySandbox(ctx context.Context, sandboxID string) (*FirecrackerVMMSlot, error)
- func (s *Store) GetIdempotentRequest(ctx context.Context, scope, fingerprint string) (*models.IdempotentRequestRecord, error)
- func (s *Store) GetMounts(ctx context.Context, sandboxID string) ([]byte, error)
- func (s *Store) GetOrCreateVolume(ctx context.Context, v *models.Volume, maxPerTenant int) (*models.Volume, bool, error)
- func (s *Store) GetPortByHostPort(ctx context.Context, hostPort int) (*models.ExposedPort, error)
- func (s *Store) GetSnapshot(ctx context.Context, name string) (*models.SandboxSnapshot, error)
- func (s *Store) GetSnapshotAlias(ctx context.Context, alias string) (*models.SnapshotAlias, error)
- func (s *Store) GetTemplate(ctx context.Context, id string) (*models.Template, error)
- func (s *Store) GetVolume(ctx context.Context, tenant, name string) (*models.Volume, error)
- func (s *Store) GetVolumeByID(ctx context.Context, tenant, id string) (*models.Volume, error)
- func (s *Store) GetWasmModule(ctx context.Context, id string) (WasmModuleRecord, error)
- func (s *Store) GetWasmStateKV(ctx context.Context, sandboxID, key string) ([]byte, bool, error)
- func (s *Store) HasActiveImageRef(ctx context.Context, image string) (bool, error)
- func (s *Store) InsertFirecrackerVMMSlot(ctx context.Context, slot FirecrackerVMMSlot, now time.Time) error
- func (s *Store) InsertWasmCheckpointPush(ctx context.Context, sandboxID, registryRef, digest string) (int64, error)
- func (s *Store) IsTemplateReferenced(ctx context.Context, id string) (bool, error)
- func (s *Store) IsTemplateReferencedByVMM(ctx context.Context, id string) (bool, error)
- func (s *Store) IsWasmDigestCatalogued(ctx context.Context, digest string) (bool, error)
- func (s *Store) IsWasmModuleReferenced(ctx context.Context, moduleID, moduleRef, moduleDigest string) (bool, error)
- func (s *Store) List(ctx context.Context) ([]*models.Sandbox, error)
- func (s *Store) ListAllCustomDomains(ctx context.Context) ([]CustomDomainRow, error)
- func (s *Store) ListAllExposedPorts(ctx context.Context) ([]models.ExposedPort, error)
- func (s *Store) ListAutoImportPendingIDs(ctx context.Context) ([]string, error)
- func (s *Store) ListByOwner(ctx context.Context, ownerRef string) ([]*models.Sandbox, error)
- func (s *Store) ListByRuntime(ctx context.Context, runtime string) ([]*models.Sandbox, error)
- func (s *Store) ListCompatState(ctx context.Context, facade string) (map[string]models.SandboxCompatState, error)
- func (s *Store) ListContainerNetnsSlotsByState(ctx context.Context, state string) ([]ContainerNetnsSlot, error)
- func (s *Store) ListCustomDomains(ctx context.Context, sandboxID string) ([]models.CustomDomain, error)
- func (s *Store) ListFirecrackerVMMSlotsForRefill(ctx context.Context, templateID string) ([]FirecrackerVMMSlot, error)
- func (s *Store) ListGCEligibleTemplates(ctx context.Context, olderThan time.Time) ([]*models.Template, error)
- func (s *Store) ListNonFreeContainerNetnsSlots(ctx context.Context) ([]ContainerNetnsSlot, error)
- func (s *Store) ListOrphanedWasmCheckpointPushes(ctx context.Context, limit int) ([]WasmCheckpointPushRecord, error)
- func (s *Store) ListPendingImageGCDue(ctx context.Context, cutoff time.Time, limit int) ([]PendingImageGCEntry, error)
- func (s *Store) ListPendingVolumeDeletions(ctx context.Context) ([]models.PendingVolumeDeletion, error)
- func (s *Store) ListReadyTemplateIDs(ctx context.Context) ([]string, error)
- func (s *Store) ListReadyWasmModuleRefs(ctx context.Context) ([]string, error)
- func (s *Store) ListReleasedFirecrackerVMMSlots(ctx context.Context, olderThan time.Time) ([]FirecrackerVMMSlot, error)
- func (s *Store) ListSnapshotAliases(ctx context.Context, facade string) (map[string]models.SnapshotAlias, error)
- func (s *Store) ListSnapshots(ctx context.Context) ([]*models.SandboxSnapshot, error)
- func (s *Store) ListSnapshotsPendingPush(ctx context.Context) ([]*models.SandboxSnapshot, error)
- func (s *Store) ListTemplates(ctx context.Context) ([]*models.Template, error)
- func (s *Store) ListTemplatesPendingPush(ctx context.Context) ([]*models.Template, error)
- func (s *Store) ListTemplatesReadyBefore(ctx context.Context, cutoff time.Time) ([]*models.Template, error)
- func (s *Store) ListUnhealthyTemplates(ctx context.Context) ([]*models.Template, error)
- func (s *Store) ListVolumes(ctx context.Context, tenant string) ([]models.Volume, error)
- func (s *Store) ListWasmCheckpointPushes(ctx context.Context, sandboxID string) ([]WasmCheckpointPushRecord, error)
- func (s *Store) ListWasmModules(ctx context.Context) ([]WasmModuleRecord, error)
- func (s *Store) ListWasmModulesOlderThan(ctx context.Context, cutoff time.Time) ([]WasmModuleRecord, error)
- func (s *Store) ListWasmStateKVKeys(ctx context.Context, sandboxID string) ([]string, error)
- func (s *Store) LiveVolumeExistsForSource(ctx context.Context, source string) (bool, error)
- func (s *Store) MarkContainerNetnsSlotRealized(ctx context.Context, sandboxID, netnsPath, containerIP string, now time.Time) (*ContainerNetnsSlot, error)
- func (s *Store) MarkFirecrackerVMMSlotFailed(ctx context.Context, slotID, errMsg string, now time.Time) error
- func (s *Store) MarkFirecrackerVMMSlotLoaded(ctx context.Context, slotID, apiSocket, runDir string, vsockCID uint32, ...) error
- func (s *Store) MarkNetworkQuotaExceeded(ctx context.Context, id string, detectedAt time.Time) error
- func (s *Store) MarkTemplatePushPending(ctx context.Context, id string) (bool, error)
- func (s *Store) MarkTemplateUnhealthy(ctx context.Context, id, reason string) (bool, error)
- func (s *Store) PutClusterSecret(ctx context.Context, rec ClusterSecretRecord) error
- func (s *Store) PutMounts(ctx context.Context, sandboxID string, sealed []byte) error
- func (s *Store) PutVolumeAttachments(ctx context.Context, attachments []models.VolumeAttachment) error
- func (s *Store) PutWasmStateKV(ctx context.Context, sandboxID, key string, value []byte) error
- func (s *Store) ReassignContainerNetnsSandbox(ctx context.Context, fromSandboxID, toSandboxID string, now time.Time) error
- func (s *Store) RefreshPendingImageGCIfExists(ctx context.Context, image string, at time.Time) (bool, error)
- func (s *Store) ReleaseContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) error
- func (s *Store) ReleaseFirecrackerTapSlot(ctx context.Context, sandboxID string) error
- func (s *Store) ReleaseFirecrackerVMMSlot(ctx context.Context, sandboxID string, now time.Time) error
- func (s *Store) ReleaseOrphanedFirecrackerVMMSlots(ctx context.Context, now time.Time) (int, error)
- func (s *Store) RemoveCustomDomain(ctx context.Context, sandboxID, hostname string) error
- func (s *Store) ReserveContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) (*ContainerNetnsSlot, error)
- func (s *Store) ResetContainerNetnsSlotToFree(ctx context.Context, slotID string, now time.Time) error
- func (s *Store) ResolveCustomDomain(ctx context.Context, hostname string) (string, error)
- func (s *Store) ResolveSandboxIDByName(ctx context.Context, name string) (string, error)
- func (s *Store) SchedulePendingImageGC(ctx context.Context, image string, at time.Time) error
- func (s *Store) SchedulePendingVolumeDeletion(ctx context.Context, v models.Volume, source string) error
- func (s *Store) SeedContainerNetnsSlot(ctx context.Context, slotID string, now time.Time) error
- func (s *Store) SeedFirecrackerTapSlot(ctx context.Context, slot FirecrackerTapSlot, now time.Time) error
- func (s *Store) SetAllowPublicTraffic(ctx context.Context, id string, allow bool, publicURL string) error
- func (s *Store) SetAutoImportPending(ctx context.Context, id string, pending bool) error
- func (s *Store) SetCustomDomainStatus(ctx context.Context, hostname string, status models.CustomDomainStatus, ...) error
- func (s *Store) SetFleetSuspended(ctx context.Context, id string, suspended bool) error
- func (s *Store) SetNetworkLimits(ctx context.Context, id string, bytesInLimit, bytesOutLimit int64) error
- func (s *Store) SetSnapshotPushState(ctx context.Context, name, state, errMsg string) error
- func (s *Store) SetTemplatePushState(ctx context.Context, id, state, errMsg string) error
- func (s *Store) SetWakeArmed(ctx context.Context, id string, armed bool) error
- func (s *Store) Touch(ctx context.Context, id string, at time.Time) error
- func (s *Store) TransferFirecrackerTapSlot(ctx context.Context, fromID, toID string, now time.Time) (*FirecrackerTapSlot, error)
- func (s *Store) TryReserveHostPort(ctx context.Context, sandboxID string, containerPort, hostPort int, ...) (ReserveHostPortResult, error)
- func (s *Store) UpdateLifecycle(ctx context.Context, id string, l models.Lifecycle) error
- func (s *Store) UpdateRuntime(ctx context.Context, id, containerID, containerIP, publicURL string) error
- func (s *Store) UpdateSandboxNetCounters(ctx context.Context, id string, deltaIn, deltaOut int64) error
- func (s *Store) UpdateSnapshotImageDistribution(ctx context.Context, name, mode, registryRef, digest string) error
- func (s *Store) UpdateStatus(ctx context.Context, id string, status models.SandboxStatus, lastError string) error
- func (s *Store) UpdateTags(ctx context.Context, id string, tags map[string]string) error
- func (s *Store) UpdateTemplatePushDistribution(ctx context.Context, id, ref, digest string) error
- func (s *Store) UpdateTemplateSnapshotFailed(ctx context.Context, id, snapshotError string) error
- func (s *Store) UpdateTemplateSnapshotReady(ctx context.Context, id, memPath, statePath string, sizeBytes int64, ...) error
- func (s *Store) UpdateTemplateStatus(ctx context.Context, id string, status models.TemplateStatus, ...) error
- func (s *Store) UpdateWasmCheckpoint(ctx context.Context, ...) error
- func (s *Store) UpdateWasmRegistryPush(ctx context.Context, sandboxID, registryRef, digest string) error
- func (s *Store) Upsert(ctx context.Context, sandbox *models.Sandbox) error
- func (s *Store) UpsertAccountMapping(ctx context.Context, ownerRef, externalID string) error
- func (s *Store) UpsertCompatState(ctx context.Context, sandboxID, facade, stateJSON string) error
- func (s *Store) UpsertPort(ctx context.Context, exposure models.ExposedPort) error
- func (s *Store) UpsertSnapshotAlias(ctx context.Context, alias models.SnapshotAlias) error
- func (s *Store) UpsertWasmModule(ctx context.Context, rec WasmModuleRecord) error
- func (s *Store) WasmDigestsInUse(ctx context.Context, digests []string) (map[string]struct{}, error)
- type WasmCheckpointPushRecord
- type WasmModuleRecord
Constants ¶
const ( NetnsSlotStateFree = "free" NetnsSlotStateReserved = "reserved" NetnsSlotStateRealized = "realized" NetnsSlotStatePooled = "pooled" NetnsSlotStateAdopted = "adopted" )
Container netns pool lifecycle states. Stored as TEXT; queries use literals.
const ( FirecrackerVMMSlotStatusSpawning = "spawning" FirecrackerVMMSlotStatusLoaded = "loaded" FirecrackerVMMSlotStatusAllocated = "allocated" FirecrackerVMMSlotStatusReleased = "released" )
Firecracker warm-VMM pool status constants. Kept as bare strings rather than a typed enum because SQLite stores them as TEXT and the store-layer queries WHERE status='...' literals — a typed wrapper would just force every call site to string()-coerce. The state machine is documented inline in the CREATE TABLE statement above.
Variables ¶
var ErrCustomDomainConflict = errors.New("custom domain hostname already taken")
ErrCustomDomainConflict is returned by AddCustomDomain when the hostname is already owned by a different sandbox. Surfaced through the API as 409. Same hostname for the same sandbox is idempotent (not a conflict) — that lets retries and reconcile re-converge without surfacing spurious errors.
var ErrCustomDomainPortMismatch = errors.New("custom domain target_port mismatch on re-add")
ErrCustomDomainPortMismatch surfaces an idempotent re-add of an already-attached hostname that carries a different target_port than the stored row. We never silently change the dial target — that would redirect live traffic without the caller knowing. The service layer translates this to HTTP 409 so the caller can detach + re-add deliberately.
var ErrJSBundleInUse = errors.New("js bundle is referenced by an active sandbox")
ErrJSBundleInUse blocks DELETE /v1/js-bundles/{digest} while an isolate sandbox still pins that bundle digest (plans/isolate-runtime.md §8).
var ErrNoFreeContainerNetnsSlot = errors.New("container netns pool: no free slot")
ErrNoFreeContainerNetnsSlot is returned when the netns pool is exhausted.
var ErrNoFreeFirecrackerTapSlot = errors.New("firecracker tap pool: no free slot")
ErrNoFreeFirecrackerTapSlot is returned by AllocateFirecrackerTapSlot when every slot is claimed. The Firecracker create path translates this into a 503-ish admission error upstream — operators see "pool exhausted" before the customer sees a confusing timeout.
var ErrNoFreeFirecrackerVMMSlot = errors.New("firecracker vmm pool: no loaded slot")
ErrNoFreeFirecrackerVMMSlot is returned by AllocateFirecrackerVMMSlot when no 'loaded' slot exists for the requested template. PR 4-B's caller treats this as the cold-spawn fallback signal, not an error state — the pool being momentarily empty is the expected behavior under load between spawn-and-load passes.
var ErrNoPooledContainerNetnsSlot = errors.New("container netns pool: no pooled slot")
ErrNoPooledContainerNetnsSlot means no prewarmed slot is available for claim.
var ErrNotFound = errors.New("sandbox not found")
var ErrSandboxNameConflict = errors.New("sandbox name already in use")
ErrSandboxNameConflict is returned by Create/Upsert when the sandbox's name collides with an existing row's name or id. Names are unique across the sandboxes table; empty names skip the name uniqueness check but ids still cannot collide with existing non-empty names.
var ErrSnapshotNameConflict = errors.New("snapshot name already in use")
var ErrTemplateIDConflict = errors.New("template id already in use")
ErrTemplateIDConflict is returned by CreateTemplate when a row with the caller-supplied ID already exists. Operators that retry POST /v1/templates with an explicit id get a 409 instead of a 500 — the standard idempotency shape the v1 API uses everywhere else.
var ErrTemplateInUse = errors.New("template is referenced by an active sandbox")
ErrTemplateInUse is the service-layer sentinel for "cannot delete: an active sandbox still names this template_id". DeleteTemplate returns it after IsTemplateReferenced returns true; the API translates it to 409. Held in the store package only because the SQL probe lives here.
var ErrVolumeExists = errors.New("volume already exists for this tenant")
ErrVolumeExists is returned by CreateVolume when the (tenant, name) pair is already taken. Facades map this to 409 Conflict. It is distinct from a generic constraint error so callers can branch on it for idempotent get-or-create semantics.
var ErrVolumeInUse = errors.New("volume is still attached")
ErrVolumeInUse is returned by DeleteVolumeIfUnattached when indexed attachments still reference the volume.
var ErrVolumeQuotaExceeded = errors.New("tenant volume quota exceeded")
ErrVolumeQuotaExceeded is returned by GetOrCreateVolume when inserting a new row would exceed the tenant's configured volume-count cap. Existing rows are returned idempotently and do not consume quota again.
var ErrWasmModuleIDConflict = errors.New("wasm module id already in use")
ErrWasmModuleIDConflict is returned when POST /v1/wasm-modules reuses an id bound to a different module_ref.
var ErrWasmModuleInUse = errors.New("wasm module is referenced by an active sandbox")
ErrWasmModuleInUse blocks DELETE while a sandbox still references the module.
Functions ¶
This section is empty.
Types ¶
type ClusterSecretRecord ¶
type ClusterSecretRecord struct {
Ref string
SandboxID string
Version int
Recipients []string
SealedPayload []byte
CreatedAt time.Time
UpdatedAt time.Time
}
ClusterSecretRecord is an opaque cluster-secret payload addressed by ref. The store never decrypts SealedPayload; service owns the envelope format.
type ContainerNetnsPoolStats ¶
type ContainerNetnsPoolStats struct {
Total int
Free int
Reserved int
Realized int
Pooled int
Adopted int
}
ContainerNetnsPoolStats reports pool occupancy.
type ContainerNetnsSlot ¶
type ContainerNetnsSlot struct {
SlotID string
NetnsPath string
ContainerIP string
SandboxID string
State string
CreatedAt time.Time
UpdatedAt time.Time
}
ContainerNetnsSlot is one row of container_netns_slots.
type CustomDomainRow ¶
type CustomDomainRow struct {
Hostname string
SandboxID string
Status models.CustomDomainStatus
LastError string
TargetPort int
CreatedAt time.Time
UpdatedAt time.Time
}
CustomDomainRow is the per-row representation read out of sandbox_custom_domains. ListAllCustomDomains returns these so the reconcile loop and the cluster FSM hydration can walk the full set.
type FirecrackerTapPoolStats ¶
FirecrackerTapPoolStats reports the current pool occupancy. Used by /healthz and the admission controller — a near-empty pool blocks new Firecracker creates upstream of the failing Allocate call, which is a better operator experience than discovering the exhaustion on the next user request.
type FirecrackerTapSlot ¶
type FirecrackerTapSlot struct {
TapName string
CIDR string
HostIP string
GuestIP string
VsockCID uint32
SandboxID string
CreatedAt time.Time
AllocatedAt time.Time
}
FirecrackerTapSlot is one pre-seeded row of the firecracker_tap_pool. Mirrors the table shape. SandboxID is empty when the slot is free, set to the owning sandbox when allocated; AllocatedAt is the zero time when free.
type FirecrackerVMMPoolStats ¶
type FirecrackerVMMPoolStats struct {
Total int
Spawning int
Loaded int
Allocated int
Released int
}
FirecrackerVMMPoolStats is the per-template breakdown by status used by /healthz and PR 4-B's refill goroutine to decide how many new slots to spawn. Total is the count of all non-deleted rows for the template; the sum of the per-status counters equals Total.
type FirecrackerVMMSlot ¶
type FirecrackerVMMSlot struct {
ID string
TemplateID string
Status string
SandboxID string
APISocket string
RunDir string
VsockCID uint32
CreatedAt time.Time
LoadedAt time.Time
AllocatedAt time.Time
ReleasedAt time.Time
LastError string
}
FirecrackerVMMSlot is one row of firecracker_vmm_pool. Mirrors the table shape; nullable DATETIME columns map to zero-valued time.Time when absent so the policy wrapper (internal/pool/vmm) doesn't have to plumb sql.NullTime through its API.
type PendingImageGCEntry ¶
PendingImageGCEntry is one row from the pending_image_gc ledger. scheduled_at travels with the image so the janitor can pin its remove/delete decision to the exact row it observed — see DeletePendingImageGCIfScheduledAt for the refresh-race rationale.
type ReserveHostPortResult ¶
type ReserveHostPortResult struct {
Reserved bool
Existing *models.ExposedPort
}
ReserveHostPortResult is the three-state outcome of TryReserveHostPort. Exactly one of Reserved/Existing/(neither) is set:
- Reserved: the row was inserted; the candidate host port is now ours.
- Existing != nil: a row for (sandbox_id, port) already exists. The allocator MUST stop walking the pool — no other host_port will satisfy the (sandbox_id, port) primary key. Caller decides whether to reuse the existing exposure or surface an error.
- both zero: the partial unique index on host_port rejected this candidate (some other sandbox owns it). Caller may retry.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
func (*Store) AddCustomDomain ¶
func (s *Store) AddCustomDomain(ctx context.Context, sandboxID, hostname string, targetPort int) error
AddCustomDomain inserts a hostname → sandbox mapping. Returns ErrCustomDomainConflict when the hostname is already owned by a different sandbox; returns ErrCustomDomainPortMismatch when the row exists for the same sandbox but with a different targetPort; returns nil when the same (hostname, sandbox, targetPort) tuple already exists (idempotent — the caller may retry safely). targetPort=0 is the toolbox-default sentinel. New rows start in CustomDomainPendingDNS.
func (*Store) AdoptContainerNetnsSlot ¶
func (s *Store) AdoptContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) (*ContainerNetnsSlot, error)
AdoptContainerNetnsSlot transitions a realized slot to adopted after the container task is running. Idempotent when already adopted.
func (*Store) AllocateFirecrackerTapSlot ¶
func (s *Store) AllocateFirecrackerTapSlot(ctx context.Context, sandboxID string, now time.Time) (*FirecrackerTapSlot, error)
AllocateFirecrackerTapSlot claims a free slot for sandboxID and returns it. Idempotent: if sandboxID already owns a slot, that slot is returned without changes (the partial unique index guarantees at most one). If no slot is free, returns ErrNoFreeFirecrackerTapSlot.
The implementation is a two-step inside the SQLite single-writer window:
- SELECT a row WHERE sandbox_id IS NULL LIMIT 1.
- UPDATE that row SET sandbox_id = ?, allocated_at = ? WHERE tap_name = ? AND sandbox_id IS NULL.
The WHERE clause on UPDATE re-checks sandbox_id IS NULL so a race with a concurrent allocate of the same row updates RowsAffected=0 and we loop. SQLite's single-writer model makes this contest rare in practice but the code stays correct under any future change.
func (*Store) AllocateFirecrackerVMMSlot ¶
func (s *Store) AllocateFirecrackerVMMSlot(ctx context.Context, templateID, sandboxID string, now time.Time) (*FirecrackerVMMSlot, error)
AllocateFirecrackerVMMSlot claims one 'loaded' slot for templateID + sandboxID. Idempotent: if sandboxID already owns a slot, that slot is returned without re-allocation (the partial unique index makes a duplicate claim a hard error, but the pre-check yields a cleaner happy path). If no 'loaded' slot for templateID exists, returns ErrNoFreeFirecrackerVMMSlot — PR 4-B's caller falls back to cold spawn rather than failing the create.
The allocator shape is lifted from AllocateFirecrackerTapSlot: SELECT one free row, UPDATE WHERE row is still free. The UPDATE's WHERE re-checks status='loaded' AND sandbox_id IS NULL so a race against a concurrent allocator updates RowsAffected=0 and we loop. SQLite's single writer makes the contest rare, but the loop keeps correctness if the locking model ever changes.
func (*Store) BeginPrewarmContainerNetnsSlot ¶
func (s *Store) BeginPrewarmContainerNetnsSlot(ctx context.Context, now time.Time) (*ContainerNetnsSlot, error)
BeginPrewarmContainerNetnsSlot reserves a free slot under its own slot_id so the refill ticker can CNI-realize it without a sandbox owner yet.
func (*Store) ClaimIdempotentRequest ¶
func (s *Store) ClaimIdempotentRequest(ctx context.Context, scope, fingerprint string, now time.Time, pendingTTL time.Duration) (*models.IdempotentRequestRecord, bool, error)
ClaimIdempotentRequest is the generic claim/replay primitive for caller-retry dedupe. scope is a facade-defined namespace string ("e2b.create" today; "daytona.create" or "v1.create" later) so the same fingerprint can be reused across facades without colliding.
Three outcomes per call:
- INSERTed a fresh pending row → acquired=true, caller owns the work.
- Found a Ready row whose ReplayUntil has not expired → acquired=false, caller replays the TargetID instead of running the work again.
- Found a Pending row whose LockedUntil has not expired → acquired=false, caller waits.
Stale Pending or Ready rows past their TTLs are reclaimed as a fresh Pending row (acquired=true), so a crashed claimer cannot block future retries indefinitely.
func (*Store) ClaimPooledContainerNetnsSlot ¶
func (s *Store) ClaimPooledContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) (*ContainerNetnsSlot, error)
ClaimPooledContainerNetnsSlot hands a prewarmed slot to sandboxID. Idempotent when sandboxID already owns a slot. Returns ErrNoPooledContainerNetnsSlot on miss.
func (*Store) ClearNetworkQuotaExceeded ¶
ClearNetworkQuotaExceeded resets the flag and the detection timestamp. Used when an operator raises the limit (or sets it to unlimited) and the counter is no longer over the new ceiling.
func (*Store) CompareCloneGeneration ¶
CompareCloneGeneration rejects stale snapshot writes when wantGen is older than the row's current clone_generation (§4.8 fencing).
func (*Store) CompleteIdempotentRequest ¶
func (s *Store) CompleteIdempotentRequest(ctx context.Context, scope, fingerprint, targetID string, now time.Time, replayTTL time.Duration) error
CompleteIdempotentRequest moves a Pending row to Ready, recording the target ID the work produced and extending the lock-and-replay window out to replayTTL from now. Returns ErrNotFound if no row matched — indicating either a programming error or a too-aggressive cleanup that removed the row mid-flight.
func (*Store) CountVolumeAttachments ¶
CountVolumeAttachments returns how many sandbox references currently point at volumeID for tenant. It is backed by idx_volume_attachments_volume and is used on Daytona delete instead of scanning every sandbox's encrypted mounts.
func (*Store) CountVolumes ¶
CountVolumes returns how many volumes tenant owns. Used for per-tenant quota enforcement at create time.
func (*Store) CreateSnapshot ¶
func (*Store) CreateTemplate ¶
CreateTemplate inserts a freshly-allocated template row. Callers set status=pending and an empty rootfs_path; the build goroutine flips both via UpdateTemplateStatus once mkfs returns. A PK collision becomes ErrTemplateIDConflict so an operator pipeline that retries POST with an explicit ID gets a 409 instead of a 500.
func (*Store) CreateVolume ¶
CreateVolume inserts a new volume row. The (tenant, name) unique index makes this the idempotency boundary: a duplicate returns ErrVolumeExists rather than a second row. CreatedAt is stamped here when the caller leaves it zero.
func (*Store) DeleteAllWasmCheckpointPushes ¶
DeleteAllWasmCheckpointPushes removes all retained AOCR push-history rows for sandboxID.
func (*Store) DeleteAllWasmStateKV ¶
DeleteAllWasmStateKV removes every durable host-KV row for sandboxID.
func (*Store) DeleteClusterSecretsForSandbox ¶
func (*Store) DeleteFirecrackerVMMSlot ¶
DeleteFirecrackerVMMSlot drops the row. PR 4-B's GC sweep calls this after the VMM process for the slot is confirmed gone, so there is no on-disk runDir or live socket the row was the last reference to. Returns ErrNotFound when the row was already deleted — idempotent on double-call.
func (*Store) DeleteIdempotentRequest ¶
DeleteIdempotentRequest drops the row outright. Used by failure paths where the in-flight write rolled back and the next retry should run the work again from scratch instead of waiting for LockedUntil.
func (*Store) DeleteMounts ¶
DeleteMounts removes mount config for a sandbox. The cascade on the sandboxes table handles this when a sandbox is destroyed; explicit deletes are useful for replacing mounts.
func (*Store) DeletePendingImageGC ¶
DeletePendingImageGC removes the ledger row for an image unconditionally. Used when the janitor decides the image is back in use (HasActiveImageRef = true) and the row should be dropped regardless of timestamp — the destroy path will re-schedule with a fresh timestamp if the image goes idle again. Missing rows are not an error.
func (*Store) DeletePendingImageGCIfScheduledAt ¶
func (s *Store) DeletePendingImageGCIfScheduledAt(ctx context.Context, image string, at time.Time) (bool, error)
DeletePendingImageGCIfScheduledAt removes the row only if its scheduled_at still matches `at` — i.e. nobody has refreshed the row since the janitor observed it. Returns whether the delete actually happened so the caller can detect the refresh race.
Why this exists: the sweep does (list, [check active, remove image, delete row]). If a destroy of another sandbox sharing the image upserts the row with a fresh timestamp between the list and the delete, an unconditional delete would silently throw away the extended TTL that destroy was supposed to buy. The janitor uses this to keep the "TTL clock restarts from the most recent destroy" contract under churn.
func (*Store) DeletePendingVolumeDeletion ¶
DeletePendingVolumeDeletion removes a reclaim-ledger row once its backend bytes have been deleted (or skipped because a live volume reclaimed the source). Idempotent: a missing row is success, so the reclaim loop can run at-least-once without tracking which rows it already cleared.
func (*Store) DeletePort ¶
func (*Store) DeleteSnapshot ¶
func (*Store) DeleteSnapshotAlias ¶
DeleteSnapshotAlias removes the alias row. FK cascade also drops the row when its underlying sandbox_snapshots row is deleted, so explicit deletes are only needed when the facade wants to forget an alias without removing the native snapshot.
func (*Store) DeleteVolume ¶
DeleteVolume removes the volume id owned by tenant. Returns ErrNotFound when no such row exists so the facade can answer 404 rather than a silent 200. Callers MUST enforce the no-live-attacher rule before calling this; the store only owns the row.
func (*Store) DeleteVolumeAttachmentsForSandbox ¶
DeleteVolumeAttachmentsForSandbox removes the indexed platform-volume references for sandboxID. SQLite normally reaches this through the sandbox FK cascade, but the explicit method lets service code share the cluster-mode cleanup path and is idempotent for rollback.
func (*Store) DeleteVolumeIfUnattached ¶
func (s *Store) DeleteVolumeIfUnattached(ctx context.Context, tenant, id, fallbackSource string) error
DeleteVolumeIfUnattached schedules backend cleanup and removes the volume row only when no indexed attachments remain. The pending cleanup row is inserted in the same transaction before the metadata row is removed, so remote data never loses its reconciliation coordinates.
fallbackSource is used only for rows created before the source column existed (vol.Source == ""); the frozen vol.Source is authoritative when present, so reclaim always targets exactly what was created even if config later changed.
func (*Store) DeleteWasmCheckpointPush ¶
DeleteWasmCheckpointPush removes one push history row by id.
func (*Store) DeleteWasmModule ¶
DeleteWasmModule removes a wasm_modules catalogue row.
func (*Store) DeleteWasmStateKV ¶
DeleteWasmStateKV removes one durable host-KV row.
func (*Store) FinishPrewarmContainerNetnsSlot ¶
func (s *Store) FinishPrewarmContainerNetnsSlot(ctx context.Context, slotID, netnsPath, containerIP string, now time.Time) error
FinishPrewarmContainerNetnsSlot moves a refill-reserved slot into the pooled warm queue (network prepaid, no sandbox owner).
func (*Store) GetClusterSecret ¶
func (*Store) GetCompatState ¶
func (s *Store) GetCompatState(ctx context.Context, sandboxID, facade string) (*models.SandboxCompatState, error)
GetCompatState returns the state blob for (sandboxID, facade), or ErrNotFound when no row exists. Callers unmarshal state_json themselves.
func (*Store) GetContainerNetnsPoolStats ¶
func (s *Store) GetContainerNetnsPoolStats(ctx context.Context) (ContainerNetnsPoolStats, error)
func (*Store) GetContainerNetnsSlotBySandbox ¶
func (s *Store) GetContainerNetnsSlotBySandbox(ctx context.Context, sandboxID string) (*ContainerNetnsSlot, error)
GetContainerNetnsSlotBySandbox returns the slot owned by sandboxID, or nil.
func (*Store) GetFirecrackerTapPoolStats ¶
func (s *Store) GetFirecrackerTapPoolStats(ctx context.Context) (FirecrackerTapPoolStats, error)
func (*Store) GetFirecrackerTapSlotBySandbox ¶
func (s *Store) GetFirecrackerTapSlotBySandbox(ctx context.Context, sandboxID string) (*FirecrackerTapSlot, error)
GetFirecrackerTapSlotBySandbox returns the slot currently owned by sandboxID, or nil if it owns none. Used by both the idempotent allocate path and the runtime driver's Inspect/Destroy paths.
func (*Store) GetFirecrackerVMMPoolStats ¶
func (s *Store) GetFirecrackerVMMPoolStats(ctx context.Context, templateID string) (FirecrackerVMMPoolStats, error)
GetFirecrackerVMMPoolStats returns per-template occupancy by status. Single GROUP BY scan covered by idx_firecracker_vmm_pool_template_status. /healthz and PR 4-C's metrics exporter both call this; PR 4-B's refill goroutine prefers ListFirecrackerVMMSlotsForRefill which gives it the row ids it may want to act on.
func (*Store) GetFirecrackerVMMSlotByID ¶
func (s *Store) GetFirecrackerVMMSlotByID(ctx context.Context, slotID string) (*FirecrackerVMMSlot, error)
GetFirecrackerVMMSlotByID returns the slot row whose id matches, or nil if not found. Lets PR 4-B's refill goroutine re-read its own freshly-inserted row to inspect the row's authoritative status (the daemon may have raced a GC between InsertFirecrackerVMMSlot and the spawner attempt). Unlike GetFirecrackerVMMSlotBySandbox, the row's sandbox_id is unknown to the caller — we project the column explicitly so an 'allocated' slot reads back with its claimant.
func (*Store) GetFirecrackerVMMSlotBySandbox ¶
func (s *Store) GetFirecrackerVMMSlotBySandbox(ctx context.Context, sandboxID string) (*FirecrackerVMMSlot, error)
GetFirecrackerVMMSlotBySandbox returns the slot currently claimed by sandboxID, or nil if it owns none. Used by the idempotent Allocate pre-check and by PR 4-B's destroy path to find the slot whose VMM process needs to be torn down.
func (*Store) GetIdempotentRequest ¶
func (s *Store) GetIdempotentRequest(ctx context.Context, scope, fingerprint string) (*models.IdempotentRequestRecord, error)
GetIdempotentRequest returns the row for (scope, fingerprint), or ErrNotFound when no row exists.
func (*Store) GetMounts ¶
GetMounts returns the encrypted mount blob, or ErrNotFound if no row exists.
func (*Store) GetOrCreateVolume ¶
func (s *Store) GetOrCreateVolume(ctx context.Context, v *models.Volume, maxPerTenant int) (*models.Volume, bool, error)
GetOrCreateVolume returns the existing (tenant,name) volume or inserts v as a new row when absent. The existence check, quota check, and insert run in one transaction so concurrent creates for different names cannot both observe the same pre-insert count and overshoot maxPerTenant. created is true only when a row was inserted by this call.
func (*Store) GetPortByHostPort ¶
GetPortByHostPort returns the raw-TCP exposure bound to hostPort, or nil if no exposure owns it. The L4 wake listener uses this to map Caddy's PROXY protocol destination port back to a sandbox/container port.
func (*Store) GetSnapshot ¶
func (*Store) GetSnapshotAlias ¶
GetSnapshotAlias returns the alias row, or ErrNotFound if the alias does not exist.
func (*Store) GetTemplate ¶
func (*Store) GetVolumeByID ¶
GetVolumeByID returns the volume with the given id scoped to tenant (so one tenant cannot resolve another's id), or ErrNotFound.
func (*Store) GetWasmModule ¶
GetWasmModule returns one wasm_modules row by catalogue id.
func (*Store) GetWasmStateKV ¶
GetWasmStateKV returns one durable host-KV value.
func (*Store) HasActiveImageRef ¶
HasActiveImageRef reports whether any sandbox row references image with a status other than destroyed. Used by image GC: when this returns false the caller may safely remove the image from Docker. Single indexed query — constant cost regardless of how many destroyed rows have accumulated, so 10k destroyed historical rows do not slow the destroy hot path. Returns true on empty image as a conservative default (caller treats it as "still in use, do not delete").
func (*Store) InsertFirecrackerVMMSlot ¶
func (s *Store) InsertFirecrackerVMMSlot(ctx context.Context, slot FirecrackerVMMSlot, now time.Time) error
InsertFirecrackerVMMSlot reserves a new row in status='spawning'. PR 4-B's refill goroutine calls this BEFORE launching firecracker so a crash mid-spawn leaves a 'spawning' row the GC sweep can clean up rather than a silently-leaked process with no row to find it by.
Validation is strict because a malformed insert is always a bug in the caller — the refill goroutine should hand us a freshly-generated id and an actual template id, not the zero value.
func (*Store) InsertWasmCheckpointPush ¶
func (s *Store) InsertWasmCheckpointPush(ctx context.Context, sandboxID, registryRef, digest string) (int64, error)
InsertWasmCheckpointPush records a successful AOCR push for keep-last-N retention.
func (*Store) IsTemplateReferenced ¶
IsTemplateReferenced reports whether any sandbox row still names this template_id. Used by DeleteTemplate (so an operator gets a 409 instead of yanking the rootfs out from under a live sandbox) and by the GC sweep (so it skips rows that are still in use). Backed by the partial index idx_sandboxes_template_id — constant cost regardless of the destroyed-row history.
func (*Store) IsTemplateReferencedByVMM ¶
IsTemplateReferencedByVMM reports whether any warm-VMM pool row still names this template. This intentionally includes released rows: even a released row is still persistent state that references the template, and template GC should not leave dangling pool rows behind. Once the VMM-pool GC deletes the row, template GC can remove the template on a later pass.
func (*Store) IsWasmDigestCatalogued ¶
IsWasmDigestCatalogued reports whether any wasm_modules row pins this content digest. The cache evictor consults it (alongside IsWasmModuleReferenced) so a digest that backs a catalogue id — resolvable later by a fresh create — is never reclaimed out from under the catalogue, even with no live sandbox.
func (*Store) IsWasmModuleReferenced ¶
func (s *Store) IsWasmModuleReferenced(ctx context.Context, moduleID, moduleRef, moduleDigest string) (bool, error)
IsWasmModuleReferenced reports whether any sandbox still names moduleRef or digest id. IsWasmModuleReferenced reports whether any sandbox row still depends on this module. The check spans ref, id, AND the resolved content digest: two aliases/tags can share the same bytes, so deleting/evicting purely by ref would yank a digest still in use by another sandbox (codex C5). A blank moduleDigest simply contributes no extra match.
func (*Store) ListAllCustomDomains ¶
func (s *Store) ListAllCustomDomains(ctx context.Context) ([]CustomDomainRow, error)
ListAllCustomDomains returns every row in the table. Used by the reconcile loop's matcher-GC pass and by the cluster FSM hydration on cold start. Ordered by hostname so reconcile diffs are stable across calls.
func (*Store) ListAllExposedPorts ¶
ListAllExposedPorts returns every row in exposed_ports across every sandbox. Used by reconcile to GC zombie caddy routes / layer4 servers without N+1 per-sandbox lookups.
func (*Store) ListAutoImportPendingIDs ¶
ListAutoImportPendingIDs returns the IDs of sandboxes whose post-pull auto-import has not yet succeeded. Returns IDs only (not full Sandbox rows) so the reconciler can fetch+retry one at a time and skip rows that have meanwhile been deleted without holding a large in-memory snapshot. Hits the partial index on (auto_import_pending = 1).
func (*Store) ListByOwner ¶
ListByOwner returns the sandboxes attributed to ownerRef, newest first. It is the owner-scoped counterpart of List: the API edge uses it to fence a user token to its own sandboxes, and the fleet enforcement loop uses it to fan a standing directive (stop/restore/delete) across one account. An empty ownerRef matches operator/PAT-created rows; callers that want the whole fleet use List instead. Ports and custom domains are intentionally not attached here — the current callers (scoping filter, enforcement) only need identity and lifecycle fields, so we skip the bulk joins.
func (*Store) ListByRuntime ¶
ListByRuntime returns the sandboxes for one runtime ("wasm", "firecracker", "docker"), newest first. It is the runtime-scoped counterpart of List: the per-runtime background sweeps (wasm periodic checkpoint, wasm durable-push retry) use it instead of List so they scan only their own rows rather than the whole fleet on every tick — at a node packing thousands of mixed-runtime sandboxes, List would load (and scanSandbox-decode) every docker/firecracker row just to filter them back out. Like ListByOwner, ports and custom domains are not attached: the sweep callers only need identity + lifecycle fields.
func (*Store) ListCompatState ¶
func (s *Store) ListCompatState(ctx context.Context, facade string) (map[string]models.SandboxCompatState, error)
ListCompatState returns every row for the given facade keyed by sandbox_id. Empty result is map of length zero, not nil — callers can always index into it.
func (*Store) ListContainerNetnsSlotsByState ¶
func (s *Store) ListContainerNetnsSlotsByState(ctx context.Context, state string) ([]ContainerNetnsSlot, error)
ListContainerNetnsSlotsByState returns all rows in the given state.
func (*Store) ListCustomDomains ¶
func (s *Store) ListCustomDomains(ctx context.Context, sandboxID string) ([]models.CustomDomain, error)
ListCustomDomains returns the canonical-ordered rows for one sandbox. Empty slice (nil) when the sandbox has no custom domains.
func (*Store) ListFirecrackerVMMSlotsForRefill ¶
func (s *Store) ListFirecrackerVMMSlotsForRefill(ctx context.Context, templateID string) ([]FirecrackerVMMSlot, error)
ListFirecrackerVMMSlotsForRefill returns every non-released slot owned by templateID. PR 4-B's refill goroutine calls this once per tick to compute "desired_depth - len(non_released)" — the spawn budget for the next pass. Released rows are excluded so a slow GC doesn't inflate the count and starve refills.
func (*Store) ListGCEligibleTemplates ¶
func (s *Store) ListGCEligibleTemplates(ctx context.Context, olderThan time.Time) ([]*models.Template, error)
ListGCEligibleTemplates returns ready/failed templates not referenced by any sandbox and last touched before olderThan. Pending rows are skipped — they have an in-flight build goroutine that owns the row's terminal transition. The anti-join against sandboxes uses the idx_sandboxes_template_id partial index so the subquery is cheap.
func (*Store) ListNonFreeContainerNetnsSlots ¶
func (s *Store) ListNonFreeContainerNetnsSlots(ctx context.Context) ([]ContainerNetnsSlot, error)
ListNonFreeContainerNetnsSlots returns rows not in the free state for reconcile.
func (*Store) ListOrphanedWasmCheckpointPushes ¶
func (s *Store) ListOrphanedWasmCheckpointPushes(ctx context.Context, limit int) ([]WasmCheckpointPushRecord, error)
ListOrphanedWasmCheckpointPushes returns push-history rows whose sandbox no longer exists, capped at limit (<=0 means a default cap). These are the rows a destroy/reconcile retained because its registry DeleteRef had not yet succeeded; the orphan-ref sweep retries each ref and drops the row once the manifest is confirmed gone, so the tracking table can never leak unbounded rows for sandboxes that are already gone.
func (*Store) ListPendingImageGCDue ¶
func (s *Store) ListPendingImageGCDue(ctx context.Context, cutoff time.Time, limit int) ([]PendingImageGCEntry, error)
ListPendingImageGCDue returns rows whose scheduled_at is at or before cutoff (the janitor passes now - ImageBuildGCTTL). Ordered by scheduled_at so the oldest entries get GC'd first within a sweep. `limit` caps the batch so a backlog (janitor disabled for a while then re-enabled, or just thousands of destroyed sandboxes sharing a few images) doesn't fan out into one huge serial Docker spike per tick — pass 0 for unbounded. scheduled_at is returned so the caller can guard the conditional delete in DeletePendingImageGCIfScheduledAt.
func (*Store) ListPendingVolumeDeletions ¶
func (s *Store) ListPendingVolumeDeletions(ctx context.Context) ([]models.PendingVolumeDeletion, error)
ListPendingVolumeDeletions exposes the durable cleanup ledger for tests and future backend-specific reclaim loops.
func (*Store) ListReadyTemplateIDs ¶
ListReadyTemplateIDs returns the IDs of every template whose artifacts are usable on this host: `status IN ('ready', 'ready_no_snapshot')`. The Phase 6 PR-D capacity heartbeat hands this list to peers so placement can prefer the node that already has the template's artifacts cached.
Returns IDs only (no payload columns) — the snapshot is gossiped every few seconds and a full row projection would balloon heartbeats once a cluster has hundreds of templates. The unknown-allow rule in placement.go nodeFits means a momentary "empty list" mid-startup is safe: peers fall back to "any host" placement until the heartbeat catches up.
func (*Store) ListReadyWasmModuleRefs ¶
ListReadyWasmModuleRefs returns module_ref values for ready catalogue rows.
func (*Store) ListReleasedFirecrackerVMMSlots ¶
func (s *Store) ListReleasedFirecrackerVMMSlots(ctx context.Context, olderThan time.Time) ([]FirecrackerVMMSlot, error)
ListReleasedFirecrackerVMMSlots is the GC sweep selector: every row in status='released' whose released_at is older than olderThan. The partial index on released_at WHERE status='released' covers this query exactly so the sweep is cheap even when the steady-state count is zero.
func (*Store) ListSnapshotAliases ¶
func (s *Store) ListSnapshotAliases(ctx context.Context, facade string) (map[string]models.SnapshotAlias, error)
ListSnapshotAliases returns all alias rows for the given facade keyed by alias. Pass empty facade to fetch every alias regardless of facade.
func (*Store) ListSnapshots ¶
func (*Store) ListSnapshotsPendingPush ¶
ListSnapshotsPendingPush returns snapshots the reconciler should retry — 'pending' is the brand-new state set by the snapshot-create path, 'error' is what a failed previous attempt left behind. 'pushing' is intentionally excluded so a row currently being processed by another reconciler tick (or a still-running goroutine kicked off by snapshot-create) is not re-claimed before its terminal state lands.
func (*Store) ListTemplates ¶
func (*Store) ListTemplatesPendingPush ¶
ListTemplatesPendingPush returns the templates the reconciler should retry: push_state IN ('pending', 'error'). 'pushing' is intentionally excluded so a row currently being processed by another reconciler tick is not re-claimed before its terminal state lands. Mirrors ListSnapshotsPendingPush exactly.
The status precondition (must be ready) keeps half-built templates from sneaking into the push queue if someone manually flipped push_state. The reconciler enforces the same guard defensively, but filtering at the source means we never even materialize the row.
func (*Store) ListTemplatesReadyBefore ¶
func (s *Store) ListTemplatesReadyBefore(ctx context.Context, cutoff time.Time) ([]*models.Template, error)
ListTemplatesReadyBefore returns the `ready` templates whose `ready_at` is older than the cutoff. Used by the Phase 6 PR-E rotation reconciler to find rebuild candidates. Only `ready` (not `ready_no_snapshot`) qualifies — rotating a ready_no_snapshot row would just re-burn build budget without delivering the rotation's goal (refreshing the snapshot's kernel + toolbox bytes).
Returns rows sorted oldest-first so a reconcile sweep that hits its per-tick fanout cap rotates the most-overdue templates first.
func (*Store) ListUnhealthyTemplates ¶
ListUnhealthyTemplates returns every template row sitting in status='unhealthy'. The daemon-start scanner in service.RekickUnhealthyTemplatesAtStart sweeps this list once at boot and kicks RebuildTemplateSnapshot for each row, closing the crash-mid-rebuild gap: if sandboxd died after MarkTemplateUnhealthy flipped the row but before the in-process kicker finished, the row would otherwise be stuck unhealthy forever — every create against that template would fail with a confusing "template unhealthy" error and only operator intervention would resolve it.
Mirrors ListTemplatesPendingPush in shape (same SELECT projection, different WHERE) so the scan path is uniform with the existing push reconciler. No status precondition beyond status='unhealthy' itself — the rebuild path inside RebuildTemplateSnapshot re-checks the row under its own read, so a row that another caller already recovered between this list and the rebuild kick is handled cleanly.
func (*Store) ListVolumes ¶
ListVolumes returns all volumes owned by tenant, newest first. Empty result is a zero-length slice, never nil.
func (*Store) ListWasmCheckpointPushes ¶
func (s *Store) ListWasmCheckpointPushes(ctx context.Context, sandboxID string) ([]WasmCheckpointPushRecord, error)
ListWasmCheckpointPushes returns push history newest-first.
func (*Store) ListWasmModules ¶
func (s *Store) ListWasmModules(ctx context.Context) ([]WasmModuleRecord, error)
ListWasmModules returns all catalogue rows newest-first.
func (*Store) ListWasmModulesOlderThan ¶
func (s *Store) ListWasmModulesOlderThan(ctx context.Context, cutoff time.Time) ([]WasmModuleRecord, error)
ListWasmModulesOlderThan returns catalogue rows not updated since cutoff.
func (*Store) ListWasmStateKVKeys ¶
ListWasmStateKVKeys lists keys for a sandbox.
func (*Store) LiveVolumeExistsForSource ¶
LiveVolumeExistsForSource reports whether any current volume row resolves to source. The reclaim worker calls this before deleting backend bytes: because sources are deterministic, a delete-then-recreate of the same name produces a new volume row pointing at the same coordinate. When that live row exists the worker must NOT delete the bytes — they now belong to the recreated volume — and simply drops the stale ledger row instead.
func (*Store) MarkContainerNetnsSlotRealized ¶
func (s *Store) MarkContainerNetnsSlotRealized(ctx context.Context, sandboxID, netnsPath, containerIP string, now time.Time) (*ContainerNetnsSlot, error)
MarkContainerNetnsSlotRealized records CNI ADD output for a reserved slot. Idempotent when already realized or adopted with the same paths.
func (*Store) MarkFirecrackerVMMSlotFailed ¶
func (s *Store) MarkFirecrackerVMMSlotFailed(ctx context.Context, slotID, errMsg string, now time.Time) error
MarkFirecrackerVMMSlotFailed records that the spawner could not produce a paused-and-loaded VMM for this slot and moves the row directly to 'released' so the GC sweep cleans it up after the TTL. Skipping the 'loaded' intermediate is intentional: a failed slot was never claimable, and a transient 'loaded' state on a row whose VMM is actually missing would let the next Allocate hand out a dead process. last_error is preserved on the row for operator triage.
func (*Store) MarkFirecrackerVMMSlotLoaded ¶
func (s *Store) MarkFirecrackerVMMSlotLoaded(ctx context.Context, slotID, apiSocket, runDir string, vsockCID uint32, now time.Time) error
MarkFirecrackerVMMSlotLoaded flips 'spawning' → 'loaded' and stamps the per-slot artifact paths the allocator will hand to the sandbox create path. The WHERE clause asserts the current state so a retried call (or a racing GC) can't accidentally walk a slot backwards from 'allocated' to 'loaded'. apiSocket and runDir live in the row so PR 4-B's runtime adapter can adopt a pre-spawned firecracker process across daemon restarts without re-deriving them.
func (*Store) MarkNetworkQuotaExceeded ¶
func (s *Store) MarkNetworkQuotaExceeded(ctx context.Context, id string, detectedAt time.Time) error
MarkNetworkQuotaExceeded flips the flag on. detectedAt records when the crossover was first observed so the API can surface it to the SDK. Calls when already-exceeded preserve the original detectedAt — the trigger time is the interesting one, not the most recent re-observation.
func (*Store) MarkTemplatePushPending ¶
MarkTemplatePushPending is the kickTemplateBuild success-path seam for Phase 6 PR 6-B.1. Idempotent and state-guarded: the WHERE clause only flips rows whose push_state is currently "active", so a row that the reconciler is already working on (pending|pushing) is left alone. push_error is cleared because a freshly-built artifact is a fresh attempt — any prior failure no longer applies.
Returns (true, nil) when the row moved, (false, nil) when the row did not exist OR was already pending/pushing/error. Callers can gate their reconciler-kick on changed=true so a no-op transition doesn't fire an extra reconciler tick.
func (*Store) MarkTemplateUnhealthy ¶
MarkTemplateUnhealthy is the Phase 6 PR-A transition for "snapshot was ready, now corrupt at load time". The WHERE status='ready' guard is the idempotency primitive: many concurrent Creates can hit the same corrupt snapshot in a burst, and only the first call's UPDATE affects a row — subsequent calls return (false, nil). Callers gate the async rebuild kick on changed=true so exactly one rebuild fires per corruption event.
has_snapshot is cleared in the same row update so the resolver and the warm-pool lister both see HasSnapshot=false on the next read — the cold-boot fallback fires until the rebuild succeeds. The snapshot artifact paths are kept on the row for forensic inspection; the rebuild overwrites them in place.
snapshot_error captures the corruption reason for operator-facing surfaces (the GET /v1/templates/{id} payload, future runbooks). The status itself is the alertable signal; the message is the human-readable detail.
func (*Store) PutClusterSecret ¶
func (s *Store) PutClusterSecret(ctx context.Context, rec ClusterSecretRecord) error
func (*Store) PutMounts ¶
PutMounts stores an encrypted mount blob for a sandbox. The blob is opaque to the store layer; encryption / decryption happens in the service layer.
func (*Store) PutVolumeAttachments ¶
func (s *Store) PutVolumeAttachments(ctx context.Context, attachments []models.VolumeAttachment) error
PutVolumeAttachments upserts the platform-volume attachments for a sandbox. The volume_id and sandbox_id foreign keys make create/delete races explicit: if a volume is deleted before the sandbox can persist its attachment, the insert fails and the service rolls the sandbox create back.
func (*Store) PutWasmStateKV ¶
PutWasmStateKV upserts one durable host-KV row (§4.6).
func (*Store) ReassignContainerNetnsSandbox ¶
func (s *Store) ReassignContainerNetnsSandbox(ctx context.Context, fromSandboxID, toSandboxID string, now time.Time) error
ReassignContainerNetnsSandbox moves adopted slot ownership from one sandbox id to another (warm park → adopt). Idempotent when toSandboxID already owns.
func (*Store) RefreshPendingImageGCIfExists ¶
func (s *Store) RefreshPendingImageGCIfExists(ctx context.Context, image string, at time.Time) (bool, error)
RefreshPendingImageGCIfExists pushes the row's scheduled_at forward when (and only when) a row for image is already present. The Create path calls this after store.Create succeeds, so a freshly-used image that previously had a pending GC gets its deadline reset from "now" instead of inheriting the original destroy's old timestamp.
UPDATE-only (not UPSERT) on purpose: a row should only ever exist when a destroy has scheduled an image for cleanup. We do NOT want the create path inserting one — that would turn pending_image_gc into a one-row-per-image-ever-used table. The row-count stays bounded by "images destroyed in the last TTL window". Returns whether a row was touched, so callers can distinguish "deadline pushed forward" from "no pending GC, nothing to push".
func (*Store) ReleaseContainerNetnsSlot ¶
func (s *Store) ReleaseContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) error
ReleaseContainerNetnsSlot returns a slot to the free pool. Idempotent.
func (*Store) ReleaseFirecrackerTapSlot ¶
ReleaseFirecrackerTapSlot returns a sandbox's slot to the pool by clearing sandbox_id + allocated_at. Idempotent: releasing a sandbox that owns no slot is a no-op.
func (*Store) ReleaseFirecrackerVMMSlot ¶
func (s *Store) ReleaseFirecrackerVMMSlot(ctx context.Context, sandboxID string, now time.Time) error
ReleaseFirecrackerVMMSlot moves a sandbox's slot from 'allocated' to 'released'. Idempotent in two senses: releasing a sandbox that never owned a slot is a no-op (RowsAffected=0 returns nil), and releasing a slot already in 'released' is a no-op for the same reason. The WHERE-on-status keeps a malformed retry from resurrecting a slot that the spawner failed and already marked released.
func (*Store) ReleaseOrphanedFirecrackerVMMSlots ¶
ReleaseOrphanedFirecrackerVMMSlots marks any warm-pool slot left in 'spawning' or 'loaded' with no sandbox claim as 'released'. The daemon calls this once at startup before refilling so rows stranded by the previous process do not stay invisible to GC forever.
func (*Store) RemoveCustomDomain ¶
RemoveCustomDomain deletes the (sandbox, hostname) row. Cross-sandbox removal is rejected — the API gets ErrNotFound rather than silently stealing a hostname from another sandbox.
func (*Store) ReserveContainerNetnsSlot ¶
func (s *Store) ReserveContainerNetnsSlot(ctx context.Context, sandboxID string, now time.Time) (*ContainerNetnsSlot, error)
ReserveContainerNetnsSlot claims a free slot for sandboxID. Idempotent when sandboxID already owns a slot.
func (*Store) ResetContainerNetnsSlotToFree ¶
func (s *Store) ResetContainerNetnsSlotToFree(ctx context.Context, slotID string, now time.Time) error
ResetContainerNetnsSlotToFree clears a slot row back to the empty free state.
func (*Store) ResolveCustomDomain ¶
ResolveCustomDomain is the hot path for the TLSAsk handler — single PK lookup, no scan. Returns ErrNotFound for unknown hostnames so the handler can fold it into a 403 without an error log on the success path. We do not surface target_port here because the routing dial target is already baked into the per-domain Caddy route at install time (see IngressCustomDomainHTTPRouteID); TLSAsk only needs the ownership signal.
func (*Store) ResolveSandboxIDByName ¶
ResolveSandboxIDByName returns the sandbox ID owning the given name, or ErrNotFound if no row matches. Empty input is rejected so an accidental "" lookup does not match a no-name sandbox via the partial unique index's escape hatch.
func (*Store) SchedulePendingImageGC ¶
SchedulePendingImageGC records (or refreshes) a pending image-deletion row. UPSERT on the image PK means concurrent or repeated destroys collapse to one row and the TTL clock restarts from the most recent destroy — so a busy churn pattern on the same image keeps deferring removal instead of racing the janitor. Empty image is a no-op.
func (*Store) SchedulePendingVolumeDeletion ¶
func (s *Store) SchedulePendingVolumeDeletion(ctx context.Context, v models.Volume, source string) error
SchedulePendingVolumeDeletion writes (or refreshes) the durable reclaim-ledger row for a volume whose metadata row lives outside this SQLite store (the cluster-FSM path), so the per-node reclaim worker still has the coordinates to delete the S3 prefix / NFS dir. The single-node path uses DeleteVolumeIfUnattached, which does this in one transaction with the row delete; this is the split-store equivalent.
func (*Store) SeedContainerNetnsSlot ¶
SeedContainerNetnsSlot inserts one free pool row. Idempotent on slot_id PK.
func (*Store) SeedFirecrackerTapSlot ¶
func (s *Store) SeedFirecrackerTapSlot(ctx context.Context, slot FirecrackerTapSlot, now time.Time) error
SeedFirecrackerTapSlot inserts one slot row into the pool. Idempotent: the tap_name PRIMARY KEY makes re-seeding with the same name a no-op, so the daemon's boot path can call this for every configured slot without coordinating across restarts. Two distinct slots with the same vsock_cid would trip the unique index — callers must precompute non-colliding CIDs (the wrapper in internal/network/tap does this).
func (*Store) SetAllowPublicTraffic ¶
func (s *Store) SetAllowPublicTraffic(ctx context.Context, id string, allow bool, publicURL string) error
SetAllowPublicTraffic flips the public-exposure flag together with the derived public_url in one statement. The expose_port opt-in path (the only way a private sandbox becomes public after create) is the caller; the two columns must move atomically because every Get materializes both — a public row with an empty public_url (or the reverse) would misreport reachability. A dedicated setter rather than Upsert so the flip doesn't race the runtime-state machine on the rest of the row.
func (*Store) SetAutoImportPending ¶
SetAutoImportPending toggles the AOCR auto-import retry flag. The post-pull auto-import path sets it to true on failure; the reconciler clears it after a successful import. The reconciler must call this rather than Upsert to avoid racing the runtime-state machine on the rest of the sandbox row.
func (*Store) SetCustomDomainStatus ¶
func (s *Store) SetCustomDomainStatus(ctx context.Context, hostname string, status models.CustomDomainStatus, lastError string) error
SetCustomDomainStatus updates the per-domain state machine. Idempotent — repeated calls with the same (status, lastError) are still write-once on updated_at, which the caller may use as a heartbeat for "we saw an ask for this host". Returns ErrNotFound when the hostname is unknown so a caller observing an issuance failure for a since-removed host gets a clean signal.
func (*Store) SetFleetSuspended ¶
SetFleetSuspended flips the fleet-suspend marker on a sandbox. The enforcement loop sets it true when a standing=suspend directive stops a running sandbox, and clears it on recovery so only fleet-suspended sandboxes are auto-restarted (a user/operator stop is left alone). Idempotent: writing the same value twice is a harmless no-op UPDATE. Returns ErrNotFound if the row is gone (already deleted), which callers treat as success — there is nothing left to converge.
func (*Store) SetNetworkLimits ¶
func (s *Store) SetNetworkLimits(ctx context.Context, id string, bytesInLimit, bytesOutLimit int64) error
SetNetworkLimits replaces the per-sandbox network byte caps. Zero means unlimited; negative values are rejected. The handler validates first so the store does not re-validate. Returns ErrNotFound if no row matches id.
func (*Store) SetSnapshotPushState ¶
SetSnapshotPushState is a narrow single-column update used by the push reconciler. errMsg is overwritten unconditionally (including to empty on success transitions) so callers don't have to remember to clear it.
func (*Store) SetTemplatePushState ¶
SetTemplatePushState is a narrow single-column update used by the push reconciler. errMsg is overwritten unconditionally (including to empty on success transitions) so callers don't have to remember to clear it. Mirrors SetSnapshotPushState.
func (*Store) SetWakeArmed ¶
SetWakeArmed toggles the wake_armed flag and bumps updated_at. The flag is set when the sandbox stops in a way that should auto-resume on the next inbound HTTP request (lifecycle idle / involuntary exit, both while Lifecycle.Serverless is true). It is cleared on a manual stop and after a successful wake. Returns ErrNotFound if no row matches id.
This is a dedicated setter rather than going through Upsert so the stop-event path and wake completion don't race the rest of the runtime state on the row (status, container_id, container_ip, etc.).
func (*Store) TransferFirecrackerTapSlot ¶
func (s *Store) TransferFirecrackerTapSlot(ctx context.Context, fromID, toID string, now time.Time) (*FirecrackerTapSlot, error)
TransferFirecrackerTapSlot re-keys an allocated TAP slot from one owner id to another without changing the TAP name, IPs, or vsock CID. The warm-VMM pool uses this when a parked slot id becomes a real sandbox id. Retrying the same transfer is idempotent once toID owns the slot; trying to overwrite a different target slot fails before the UPDATE hits the partial unique index.
func (*Store) TryReserveHostPort ¶
func (s *Store) TryReserveHostPort(ctx context.Context, sandboxID string, containerPort, hostPort int, protocol, publicURL string, now time.Time) (ReserveHostPortResult, error)
TryReserveHostPort attempts to claim hostPort for (sandboxID, containerPort) in a single INSERT OR IGNORE. The OR IGNORE swallows two distinct UNIQUE failures — the (sandbox_id, port) primary key AND the partial index on host_port — so on a no-op insert we follow up with a SELECT to disambiguate. Without that disambiguation, retrying expose for an already-exposed port looks identical to a host_port collision and walks the whole allocator pool before failing with "exhausted".
func (*Store) UpdateLifecycle ¶
UpdateLifecycle replaces the lifecycle fields on a sandbox row (the four timers plus the serverless opt-in) and bumps updated_at. Other fields are untouched. Returns ErrNotFound if no row matches id. The caller must validate the Lifecycle first; the store does not re-validate (it would couple two layers for no gain). wake_armed is intentionally NOT touched here — it transitions on stop/wake events, not on lifecycle edits.
func (*Store) UpdateRuntime ¶
func (*Store) UpdateSandboxNetCounters ¶
func (s *Store) UpdateSandboxNetCounters(ctx context.Context, id string, deltaIn, deltaOut int64) error
UpdateSandboxNetCounters bumps the cumulative ingress/egress counters by the given deltas. Both values are non-negative byte counts measured since the last sample. Concurrent calls are serialized by SQLite's single writer, and the UPDATE is atomic so a failed sample never partially applies. Returns ErrNotFound if the sandbox row was deleted between the poller's snapshot and this write — the netstats poller treats that as a cleanup signal and drops the in-memory baseline.
func (*Store) UpdateSnapshotImageDistribution ¶
func (s *Store) UpdateSnapshotImageDistribution(ctx context.Context, name, mode, registryRef, digest string) error
UpdateSnapshotImageDistribution flips the distribution metadata on a snapshot row after a successful AOCR push — local_only → aocr. Called from the reconciler success path together with SetSnapshotPushState. VerifiedAt records when the push completed; cluster placement on other nodes uses this together with the new mode to decide the snapshot is fan-outable.
func (*Store) UpdateStatus ¶
func (*Store) UpdateTags ¶
UpdateTags replaces sandboxes.tags_json on the row matching id and bumps updated_at. Used by facades that want to mutate the native tags field without round-tripping the entire sandbox struct through Upsert. Returns ErrNotFound if no row matches.
func (*Store) UpdateTemplatePushDistribution ¶
UpdateTemplatePushDistribution stamps the registry destination metadata after a successful AOCR push. ref is the canonical repo:tag the daemon pushed; digest is the manifest digest the registry surfaced via the push stream's `aux` payload (may be empty). Called from the reconciler success path together with SetTemplatePushState.
Written in one statement so a crash between the two fields cannot land a half-filled row — the consumer-side pull in PR 6-B.2 sees either both fields populated or both empty.
func (*Store) UpdateTemplateSnapshotFailed ¶
UpdateTemplateSnapshotFailed records the snapshot-phase error and flips status to ready_no_snapshot. The rootfs columns are untouched — the caller has already populated them via UpdateTemplateStatus during the rootfs phase, and the cold-boot fallback still needs the rootfs path intact. has_snapshot stays 0 (column default) so readers correctly skip the snapshot-load path.
func (*Store) UpdateTemplateSnapshotReady ¶
func (s *Store) UpdateTemplateSnapshotReady(ctx context.Context, id, memPath, statePath string, sizeBytes int64, checksum string, vsockCID uint32, hasOverlay bool) error
UpdateTemplateSnapshotReady is the terminal-success seam for the snapshot phase. Writes the snapshot artifact metadata and flips status=ready / has_snapshot=1 / has_overlay=hasOverlay in one UPDATE so a concurrent reader (CreateSandbox racing the build goroutine) never observes "status=ready but the snapshot fields are still zero". snapshot_error is unconditionally cleared so a retried build that finally succeeds doesn't carry a stale message. hasOverlay is true for every PR-B-built template (the snapshot capture path always includes the overlay placeholder); kept as a parameter so a future "snapshot without overlay" build profile (e.g. a tiny boot-only template) does not require a schema change.
func (*Store) UpdateTemplateStatus ¶
func (s *Store) UpdateTemplateStatus(ctx context.Context, id string, status models.TemplateStatus, rootfsPath, lastError string, sizeBytes int64) error
UpdateTemplateStatus is the rootfs-phase seam the build goroutine uses to transition between pending / building_rootfs / ready / ready_no_snapshot / failed. rootfsPath, sizeBytes, and lastError are overwritten unconditionally (including to empty on the success path) so a retried build that succeeds doesn't have to remember to clear stale error text. ready_at is stamped on the ready and ready_no_snapshot transitions (both are terminal-and-usable states); the GC sweep treats "no ready_at" as "never finished building" and leaves the row alone for the build goroutine to finish or fail.
The snapshot phase uses UpdateTemplateSnapshotReady / Failed instead so the snapshot columns and the ready transition land in one row update — readers never observe "status=ready but has_snapshot=0".
func (*Store) UpdateWasmCheckpoint ¶
func (s *Store) UpdateWasmCheckpoint(ctx context.Context, sandboxID, status, checkpointPath, cloneGen, lastError string) error
UpdateWasmCheckpoint persists passivation metadata on a sandbox row.
func (*Store) UpdateWasmRegistryPush ¶
func (s *Store) UpdateWasmRegistryPush(ctx context.Context, sandboxID, registryRef, digest string) error
UpdateWasmRegistryPush records the AOCR ref/digest after a durable checkpoint push.
func (*Store) UpsertAccountMapping ¶
UpsertAccountMapping records (or refreshes) an identity resolved by the fleet control plane. first_seen is preserved across calls; last_seen advances to now. Idempotent by owner_ref PK. Open-source builds never call this (no validator resolves user tokens); managed builds call it at create time, not per request, to keep the auth hot path write-free.
func (*Store) UpsertCompatState ¶
UpsertCompatState writes the facade-private state blob for (sandboxID, facade). stateJSON is opaque to the store — each facade defines its own schema inside it. created_at is preserved on update so list ordering stays stable.
func (*Store) UpsertPort ¶
func (*Store) UpsertSnapshotAlias ¶
UpsertSnapshotAlias maps a facade-shaped alternate identifier onto a native sandbox_snapshots row. created_at is preserved on update.
func (*Store) UpsertWasmModule ¶
func (s *Store) UpsertWasmModule(ctx context.Context, rec WasmModuleRecord) error
UpsertWasmModule inserts or updates a wasm_modules catalogue row.
func (*Store) WasmDigestsInUse ¶
func (s *Store) WasmDigestsInUse(ctx context.Context, digests []string) (map[string]struct{}, error)
WasmDigestsInUse returns the subset of digests that are still referenced by a live sandbox OR pinned by a catalogue row. The cache evictor calls this ONCE per sweep with every candidate digest instead of two probes per file, so a large cache no longer issues O(files) serialized queries against the single-writer DB (codex P1). Digests are chunked to stay under SQLite's bound parameter limit.
type WasmCheckpointPushRecord ¶
type WasmCheckpointPushRecord struct {
ID int64
SandboxID string
RegistryRef string
Digest string
PushedAt time.Time
}
WasmCheckpointPushRecord is one AOCR push history row.
type WasmModuleRecord ¶
type WasmModuleRecord struct {
ID string
ModuleRef string
Status string
ModulePath string
ModuleSizeBytes int64
Digest string
Entrypoint string
HasWarm bool
LastError string
CreatedAt time.Time
UpdatedAt time.Time
ReadyAt *time.Time
}
WasmModuleRecord is one row in wasm_modules.