Documentation
¶
Overview ¶
Package store is simbroker's machine-global state: the set of live claims, persisted to a JSON file and guarded so that concurrent simbroker processes (CLI invocations, the MCP server, other projects) never corrupt it or race on capacity.
Correctness rules, each one load-bearing (and each verified during design):
- Lock a dedicated sidecar file ("lock"), NEVER state.json itself. An atomic write replaces state.json's inode via rename; a flock held on the old inode would be silently stranded, giving zero mutual exclusion. The sidecar is never renamed, so its inode is stable.
- Hold the flock across the WHOLE read-modify-write (load -> mutate -> write), not just the write — that's what makes capacity checks race-free.
- flock auto-releases when the process dies (even on SIGKILL), so no cleanup handler is needed for crash safety.
- flock is unreliable for intra-process exclusion, so an in-process mutex guards goroutines in the same process in addition to the cross-process flock.
- Writes are atomic: temp file in the same dir, fsync, rename, fsync dir.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultDir ¶
func DefaultDir() string
DefaultDir resolves the state directory: $SIMBROKER_DIR, else $XDG_STATE_HOME/simbroker, else ~/.simbroker.
Types ¶
type Claim ¶
type Claim struct {
ID string `json:"id"`
UDID string `json:"udid"` // opaque device identity: iOS UDID, or Android AVD name
// Class is the device class ("ios"|"android"). Added after v1; an empty
// value (a pre-upgrade claim, or one written by an older binary) means iOS —
// always read it through ClassOrDefault, never the bare field.
Class string `json:"class,omitempty"`
DeviceName string `json:"device_name"`
Label string `json:"label,omitempty"`
PID int `json:"pid,omitempty"` // holder pid; 0 = no liveness signal, TTL governs
PIDStart string `json:"pid_start,omitempty"` // start-time fingerprint guarding against pid reuse
Hostname string `json:"hostname,omitempty"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
RenewedAt time.Time `json:"renewed_at"`
}
Claim is one lease on one device.
func (Claim) ClassOrDefault ¶
ClassOrDefault is the SINGLE source of truth for a claim's class: an empty Class (pre-upgrade state, or an older binary) is iOS. Every place that consults class — capacity counting, selection, reclaim — must use this so a legacy claim can never leak into another class's code path.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a handle to the on-disk state directory.