Documentation
¶
Overview ¶
Package env owns the daemon's environment-variable handling: port allocation (with refcounting), value synthesis (HOST / URL for allocated ports), cross-service propagation, and operator un-prefix —.
The package exposes two surfaces:
Allocator — picks free host ports, tracks refcounts, frees on release.
Builder — assembles the full env block for one service, including
constants from compose, allocated values, derived values,
and cross-service references resolved against other
services' allocations.
The runner calls Builder.ForTarget at process spawn time and Allocator.ReleaseForTarget when the process terminates. Server's GetEnv RPC calls Builder.ForService for read-only inspection.
Index ¶
- func ServicePrefix(serviceName string) string
- type Allocation
- type Allocator
- func (a *Allocator) Acquire(owner, localVar, consumer string) (int, error)
- func (a *Allocator) Lookup(owner, localVar string) (int, bool)
- func (a *Allocator) Release(consumer string)
- func (a *Allocator) Reserve(owner, localVar string, port int, consumer string) int
- func (a *Allocator) Services() []string
- func (a *Allocator) SetServices(names []string)
- func (a *Allocator) Snapshot() []Allocation
- type Builder
- type Entry
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ServicePrefix ¶
ServicePrefix is the uppercase, underscore-separated form of a service name used in cross-service env references. The convention turns `service-json-keys` into `SERVICE_JSON_KEYS`; the resulting prefix is what other services prepend when consuming this service's vars: `${SERVICE_JSON_KEYS_GRPC_PORT}`.
Types ¶
type Allocation ¶
Allocation is one snapshot row.
type Allocator ¶
type Allocator struct {
// contains filtered or unexported fields
}
Allocator picks free host ports for `*_PORT` env variables and tracks refcounts so an allocation is freed only when its last consumer terminates. Local-dev convention: ephemeral range, kernel-assigned, no fixed pool.
The (ownerService, localVar) tuple is the unique key. Cross-service references resolve by looking up the owner's allocation; the consumer is added to the refs list without taking a separate slot.
func NewAllocator ¶
func NewAllocator() *Allocator
NewAllocator returns an empty allocator. Call SetServices to register the cross-service prefix vocabulary before any allocation.
func (*Allocator) Acquire ¶
Acquire returns the host port for (owner, localVar), allocating a fresh one if no slot exists. `consumer` is the target ID claiming this slot; repeated calls with the same consumer are idempotent. Spec §6.2.
func (*Allocator) Lookup ¶
Lookup returns the current port for (owner, localVar) WITHOUT allocating. Returns (0, false) if no slot exists. Used by the Builder for the read-only ForService path (`a-novel run env`).
func (*Allocator) Release ¶
Release decrements every slot the given consumer was holding. A slot whose refcount hits zero is removed (its port returned to the ephemeral pool simply by virtue of nobody binding it). Idempotent.
func (*Allocator) Reserve ¶
Reserve records (owner, localVar) → port WITHOUT consulting the kernel. Used by adoption: when the daemon restarts and finds an already-running infra container with port mapping host:N → container:5432, it calls Reserve to re-seed the slot so subsequent Acquire calls (e.g., for the one-shot migrations target) return the same host port the running container is bound to. Idempotent for matching (owner, localVar, port); refuses to overwrite a conflicting port already recorded (returns the existing port instead).
func (*Allocator) Services ¶
Services returns a snapshot of the registered service names. Read-only helper for callers that need to resolve owners without grabbing the internal lock.
func (*Allocator) SetServices ¶
SetServices registers the universe of service names the allocator should recognize as cross-service prefixes. Sorts longest-first so shadowing (e.g., `service-template-extra` vs `service-template`) resolves to the longer name.
func (*Allocator) Snapshot ¶
func (a *Allocator) Snapshot() []Allocation
Snapshot returns every current allocation. Stable order keyed by (owner, localVar) so output is deterministic.
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder assembles env blocks for services / targets. It reads compose values from the discovery snapshot and resolves references against the shared Allocator.
func NewBuilder ¶
NewBuilder wraps an Allocator. The Allocator must have SetServices called before the first ForTarget invocation.
func (*Builder) ForService ¶
ForService is the read-only variant. Used by the GetEnv RPC so users can inspect the env without side-effecting the allocator. Vars whose allocations haven't been acquired yet appear with empty string values.
func (*Builder) ForServiceUp ¶
func (b *Builder) ForServiceUp(svc *discovery.Service, allServices []string, consumer string) ([]Entry, error)
ForServiceUp is the allocate-on-demand variant of ForService — used when bringing infra up so the daemon claims `${*_PORT}` slots referenced by infra services (e.g., postgres-X's `${POSTGRES_PORT}`). Consumer is the service-level synthetic ID ("<stack>/<service>-infra") so KillInfra can Release the slots cleanly.
func (*Builder) ForTarget ¶
ForTarget builds the env block to pass to a spawned process for the given target. Allocations are CREATED here — the target is recorded as the consumer for every `*_PORT` it references (directly or via cross-service), and Allocator.Release(targetID) frees them.
The return shape is []string in "KEY=VALUE" form, ready for exec.Cmd.Env. Use BuildResult.ToMap if you want the same content as a map (e.g., for JSON output via GetEnv).