Documentation
¶
Overview ¶
Package lockfile implements the adapter lockfile state (graph-backend-adapter-contract §10.1).
The lockfile pins each activated adapter's source and schema digests and tracks a per-materialized-view state machine for cross-adapter cutover. This package provides the value types, the view_status enumeration (§10.1.1), state-machine init on activation, and fail-closed reconciliation (§10.1.3). Cross-adapter transitions beyond init/reconcile are owned by later tasks in this plan.
Persistence is NOT hand-rolled here. Adapter state is the "adapters" section of the shared .agentsrc.lock document (config-distribution-model §7.4): Load/Save route through internal/agentslock, which owns the whole JSON document, the atomic write, and the preservation of sibling sections (config, packages, …). The path argument is always the canonical config.AgentsLockPath — never a standalone *.lock file.
Index ¶
- func Digest(data []byte) string
- func Save(path string, lf *Lockfile) error
- type Adapter
- type Inconsistency
- type Lockfile
- func (lf *Lockfile) Activate(name, sourceDigest, schemaDigest string, now time.Time)
- func (lf *Lockfile) ActivationBlockers(dependee string) []string
- func (lf *Lockfile) AdapterNames() []string
- func (lf *Lockfile) MarkDependeeBumped(dependee string, now time.Time) []string
- func (lf *Lockfile) MarkViewRebuilt(adapter, view, viewDigest string, now time.Time) error
- func (lf *Lockfile) Reconcile(present ViewPresenceFunc, now time.Time) []Inconsistency
- func (lf *Lockfile) RegisterView(adapter, view, viewDigest string, deps []ViewDependency, now time.Time)
- func (lf *Lockfile) ResolveRecompat(adapter, view string, compatible bool, deps []ViewDependency, now time.Time) error
- func (lf *Lockfile) ViewStatusOf(adapter, view string) (ViewStatus, bool)
- type StateTransition
- type View
- type ViewDependency
- type ViewPresenceFunc
- type ViewStatus
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Save ¶
Save stages the lockfile as the "adapters" section of the .agentsrc.lock document at path and flushes it atomically via agentslock (§7.4). Any sibling sections already present (config, packages, …) are preserved verbatim: Save opens the live document, replaces only "adapters", and writes the whole thing back. The shared writer owns the atomic temp-file+rename.
Types ¶
type Adapter ¶
type Adapter struct {
SourceDigest string `json:"source_digest"`
SchemaDigest string `json:"schema_digest"`
ActivatedAt string `json:"activated_at"`
MaterializedViews map[string]*View `json:"materialized_views,omitempty"`
}
Adapter is the per-adapter lockfile state (§10.1).
type Inconsistency ¶
type Inconsistency struct {
Adapter string
View string
From ViewStatus
To ViewStatus
Reason string
}
Inconsistency is one reconciliation finding (§10.1.3).
type Lockfile ¶
Lockfile is the in-memory view of the "adapters" section of .agentsrc.lock (§10.1). It is a typed projection of one section; the surrounding document (config, packages, lock_version) is owned and preserved by agentslock.
func Load ¶
Load reads the "adapters" section of the .agentsrc.lock document at path. A missing file or absent section yields an empty lockfile and no error (a not-yet-initialized graph is valid). Sibling sections (config, packages) are not loaded here — they belong to other writers (§7.4).
func (*Lockfile) Activate ¶
Activate registers (or refreshes) an adapter's lockfile entry on activation, initializing the per-adapter state machine. sourceDigest is the digest of the adapter YAML; schemaDigest is the canonical schema hash. Re-activating an existing adapter updates its digests and activation time while preserving its materialized-view state.
func (*Lockfile) ActivationBlockers ¶ added in v0.5.0
ActivationBlockers returns the dependent "adapter/view" keys in dsl-update-required that depend_on dependee, in sorted order. A non-empty result BLOCKS dependee (re)activation (§10.3 mechanical gate): the dependee cannot go live until every incompatible dependent ships an updated query that clears the block.
func (*Lockfile) AdapterNames ¶
AdapterNames returns the activated adapter names in sorted order.
func (*Lockfile) MarkDependeeBumped ¶ added in v0.5.0
MarkDependeeBumped freezes every ready view that depends_on dependee into pending-recompat-check (§10.3 step 1: a dependee schema bump suspends its dependents until each view's DSL is re-validated). It returns the affected "adapter/view" keys in sorted order. Views not currently ready are left as-is (a view already mid-cutover is not re-frozen).
func (*Lockfile) MarkViewRebuilt ¶ added in v0.5.0
MarkViewRebuilt transitions a pending-rebuild view to ready after the bootstrap recomputes its rows (§10.3), recording the rebuilt view digest. It errors if the view is not in pending-rebuild.
func (*Lockfile) Reconcile ¶
func (lf *Lockfile) Reconcile(present ViewPresenceFunc, now time.Time) []Inconsistency
Reconcile performs the fail-closed reconciliation pass (§10.1.3). It cross-checks each ready view against on-disk presence via present and flips lockfile state per the §10.1.3 table. It never deletes view rows; it only mutates lockfile state. The returned slice lists every state change. A nil presence func treats every view as absent (the conservative case).
func (*Lockfile) RegisterView ¶ added in v0.5.0
func (lf *Lockfile) RegisterView(adapter, view, viewDigest string, deps []ViewDependency, now time.Time)
RegisterView records a materialized view's initial lockfile state on the consumer adapter as ready: the view was just compiled and (re)built against the recorded dependency digests (§10.1). It creates the consumer adapter entry if absent. Re-registering replaces the view's recorded dependencies and digest and resets it to ready (a fresh build).
func (*Lockfile) ResolveRecompat ¶ added in v0.5.0
func (lf *Lockfile) ResolveRecompat(adapter, view string, compatible bool, deps []ViewDependency, now time.Time) error
ResolveRecompat applies the mechanical cutover gate result (§10.3) to a view in pending-recompat-check: compatible → pending-rebuild (recording the new dependency digests the view will rebuild against); incompatible → dsl-update-required (the dependent must ship a new query; O1 — no accepts_breaking_changes opt-out). It errors if the view is not in pending-recompat-check (the only state from which recompat resolves).
func (*Lockfile) ViewStatusOf ¶ added in v0.5.0
func (lf *Lockfile) ViewStatusOf(adapter, view string) (ViewStatus, bool)
ViewStatusOf returns a view's current status and whether it is recorded.
type StateTransition ¶
type StateTransition struct {
At string `json:"at"`
From ViewStatus `json:"from,omitempty"`
To ViewStatus `json:"to"`
Trigger string `json:"trigger"`
}
StateTransition is one entry in a view's bounded audit log (§10.1.1).
type View ¶
type View struct {
ViewDigest string `json:"view_digest,omitempty"`
ViewStatus ViewStatus `json:"view_status"`
DependsOn []ViewDependency `json:"depends_on,omitempty"`
LastRebuiltAt string `json:"last_rebuilt_at,omitempty"`
LastValidationAt string `json:"last_validation_at,omitempty"`
StateHistory []StateTransition `json:"state_history,omitempty"`
}
View is the per-materialized-view lockfile state (§10.1).
type ViewDependency ¶
type ViewDependency struct {
Adapter string `json:"adapter"`
SchemaDigest string `json:"schema_digest"`
Version string `json:"version"`
}
ViewDependency records a dependee's schema digest at the time the view was last rebuilt and validated (§10.1).
type ViewPresenceFunc ¶
ViewPresenceFunc reports, for an adapter and view, whether the view tables are present on disk and (if present) the on-disk schema digest. Reconcile uses it to compare against the lockfile's recorded view_digest.
type ViewStatus ¶
type ViewStatus string
ViewStatus is the normative four-value enum from §10.1.1.
const ( // StatusReady — view tables present and digest matches. StatusReady ViewStatus = "ready" // StatusPendingRecompatCheck — a dependee bumped; re-validate the view DSL. StatusPendingRecompatCheck ViewStatus = "pending-recompat-check" // StatusPendingRebuild — validation passed; bootstrap must rebuild. StatusPendingRebuild ViewStatus = "pending-rebuild" // StatusDSLUpdateRequired — incompatible dependee; dependent must ship a new query. StatusDSLUpdateRequired ViewStatus = "dsl-update-required" )
func (ViewStatus) Valid ¶
func (s ViewStatus) Valid() bool
Valid reports whether s is one of the four normative statuses.