Documentation
¶
Overview ¶
Package placement is a durable admission primitive, not a scheduler or an execution engine. Only trusted control-plane callers may configure policy or submit retirement attestations. Workers must separately enforce fences before starting/publishing/stopping work. Lease expiry revokes authority, never proves process retirement, and never frees capacity.
Index ¶
- type Claim
- type Controller
- type Error
- type Fence
- type History
- type HistoryKey
- type Options
- type QuotaStatus
- type ReceiptVerifier
- type Record
- type RenewalSummary
- type Request
- type RetirementReceipt
- type RetirementVerifier
- type Service
- func (s *Service) EnsureLedgerQuota(ctx context.Context) error
- func (s *Service) LedgerStatus(ctx context.Context) (QuotaStatus, error)
- func (s *Service) LedgerUsage(ctx context.Context) (used, retired int, err error)
- func (s *Service) Lookup(ctx context.Context, session string) (Record, error)
- func (s *Service) RaiseLedgerQuota(ctx context.Context, expected int) error
- func (s *Service) RemoveTarget(ctx context.Context, target Target, evidence string) error
- func (s *Service) Renew(ctx context.Context, f Fence, deadline time.Time) error
- func (s *Service) Reserve(ctx context.Context, request Request) (Record, error)
- func (s *Service) Retire(ctx context.Context, f Fence, evidence string) error
- func (s *Service) RetireDisplaced(ctx context.Context, f Fence, evidence string) error
- func (s *Service) SetPool(ctx context.Context, scope string, role config.NodeRole, capacity int64) error
- func (s *Service) SetTarget(ctx context.Context, target Target, roles config.NodeRoles, ...) error
- func (s *Service) Supersede(ctx context.Context, failed Fence, request Request, ...) (Record, error)
- type Target
- type UnknownOutcome
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Controller ¶
type Controller struct{ ID, Boot string }
type Error ¶
type Error string
const ( ErrInvalid Error = "placement: invalid request" ErrFenced Error = "placement: stale fence or generation" ErrConflict Error = "placement: operation payload conflict" ErrCapacity Error = "placement: capacity exhausted" ErrPolicy Error = "placement: missing or ineligible target/scope policy" ErrRetirement Error = "placement: retirement proof required" ErrQuotaPolicy Error = "placement: fleet ledger quota differs; coordinate deployment policy" ErrQuota Error = "placement: session ledger quota exhausted" )
const ErrReceiptUnknown Error = "placement: exact retirement receipt unknown"
type Fence ¶
type Fence struct {
Session string
Generation int64
Controller Controller
Target Target
}
type History ¶
type History struct {
// contains filtered or unexported fields
}
History shares its explicitly supplied placement Service's DB and transaction policy. It owns no workers or goroutines. The namespace is trusted host config, never a caller request field; the DB also pins a single namespace for this ledger.
func NewHistory ¶
func NewHistory(service *Service, configuredCluster string, verifier ReceiptVerifier) (*History, error)
func (*History) Lookup ¶
func (h *History) Lookup(ctx context.Context, k HistoryKey) (RetirementReceipt, error)
Lookup returns exact persisted trusted evidence or unknown. It neither infers retirement from a generation floor nor supplies current execution authority.
func (*History) Record ¶
func (h *History) Record(ctx context.Context, r RetirementReceipt) error
Record publishes evidence only for an already retired current exact fence. It cannot release claims. If replacement wins first, it fails closed. Prefer RetireWithReceipt to avoid that publication/replacement gap. Immutable replay of an existing trusted receipt succeeds after replacement without re-verifying discarded local payloads. Conflicting replay is always rejected.
func (*History) RetireWithReceipt ¶
func (h *History) RetireWithReceipt(ctx context.Context, r RetirementReceipt, evidence string) error
RetireWithReceipt invokes BOTH trusted verifiers before taking placement:all, then atomically rechecks the full current fence and persists the receipt with the normal Retire claim release. An existing immutable receipt is read-only reconciliation and needs no fresh proof. UnknownOutcome requires exact Lookup; never discard local ownership on an unconfirmed result. No quota/floor is freed.
type HistoryKey ¶
HistoryKey identifies one exact generation in the configured cluster. A higher generation or a missing row is never an exact historical retirement receipt.
type QuotaStatus ¶
type ReceiptVerifier ¶
type ReceiptVerifier interface {
VerifyReceipt(context.Context, RetirementReceipt) error
}
ReceiptVerifier is a trusted host dependency, not a wire decoder. It MUST bind Key.Cluster to the actual configured cluster authority, authenticate the full fence, request hash and source owner/PlayID/revision/size, and independently establish exact encoder AND local input AND source-owner retirement. Source proof includes backend Done+nil Err and joined producers, not merely zero holds. NeverStarted requires an irreversible exact negative admission tombstone. Accepted renewal history must be worker-accepted, not just source-extended. Digests alone, silence, expiry and missing status are never proof. Verification runs outside placement locks; callers must retain ownership through publication.
type Record ¶
type Record struct {
InitialDeadline time.Time // immutable Reserve result; replay never inherits a renewal
Fence
Operation string
Role config.NodeRole
Deadline time.Time
Retired, Authority bool
Claims []Claim // immutable requested allocation, including after retirement
}
Record is the current durable assignment. Authority is a fresh DB-clock observation, not a permit to execute indefinitely. Deadline is unchanged on Reserve replay. Retired assignments must never be started, even on replay.
type RenewalSummary ¶
type RenewalSummary struct {
Operation, PreviousVersion uint64
PreviousDeadline, Deadline time.Time
}
RenewalSummary preserves only the last worker-accepted CAS, never source-only extension evidence. It grants no authority and cannot be replayed as a renewal.
type RetirementReceipt ¶
type RetirementReceipt struct {
Key HistoryKey
Operation string // placement reservation operation
RequestHash [32]byte
NeverStarted bool
Source Target
PlayID, Revision string
Size int64
EncoderProof, InputProof, SourceProof [32]byte
InitialDeadline time.Time
Renewable bool
Renewal *RenewalSummary
}
RetirementReceipt contains bounded identifiers and SHA-256 digests, never raw credentials, capabilities, URLs or proof payloads. RequestHash commits the exact immutable worker Start encoding. NeverStarted is reserved for authenticated stop-before-start proof whose admission barrier was sealed before attestation; it is not inferred from missing records. All three proofs remain mandatory.
type RetirementVerifier ¶
RetirementVerifier validates authenticated exact-fence retirement, or a trusted operator attestation that the old execution host has been externally fenced. Network silence, node absence, and elapsed deadlines are NOT sufficient proof. It runs outside transactions; the full fence is rechecked afterwards.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func (*Service) EnsureLedgerQuota ¶
EnsureLedgerQuota seeds or verifies the fleet's durable admission ceiling. It never raises an existing policy. Every fresh Reserve checks this same row under the placement transaction lock; stale coordinator settings fail closed.
func (*Service) LedgerStatus ¶
func (s *Service) LedgerStatus(ctx context.Context) (QuotaStatus, error)
func (*Service) LedgerUsage ¶
LedgerUsage exposes quota pressure. Retired rows ARE compact tombstones: claims are removed, but the fixed-size fence, generation and operation digest survive forever. There is intentionally no TTL deletion API: discarding a floor would allow an arbitrarily delayed generation-zero replay to resurrect old work. Raise MaxSessions consistently across coordinators or archive/replace the whole cluster namespace under externally established quiescence when quota is reached.
func (*Service) Lookup ¶
Lookup reconciles unknown outcomes. Its snapshot and authority observation are serialized with mutations, so a mixed old fence/new claims record is impossible.
func (*Service) RaiseLedgerQuota ¶
RaiseLedgerQuota is an explicit monotonic compare-and-swap operation for a trusted operator. Updating deployment JSON alone cannot raise the fleet policy. Old coordinators keep existing-work renewal/retirement but cannot allocate new generations until configured with the newly committed ceiling.
func (*Service) RemoveTarget ¶
RemoveTarget is an explicit trusted operator attestation that an exact boot has been permanently removed/fenced. It is never called by liveness pruning. That incarnation cannot be admitted again. A future boot is independent.
func (*Service) Renew ¶
Renew uses an absolute deadline, so retries cannot extend the requested lease. It cannot revive expired authority. A stale renewal never touches replacements.
func (*Service) Reserve ¶
Reserve atomically admits all scopes or none. ExpectedGeneration=0 creates a new logical session; replacement requires the current retired generation. Idempotency keys are scoped to a session generation transition. Old replay is fenced by ExpectedGeneration after a replacement, including after compaction.
func (*Service) Retire ¶
Retire is the ONLY capacity release operation, including after timeout or permanent node loss. Proof verification runs before taking the component lock; an exact-fence recheck prevents stale proof from releasing a replacement.
func (*Service) RetireDisplaced ¶
RetireDisplaced releases only an exactly verified former execution. Silence, missing membership and lease expiry are never accepted as process exit proof.
func (*Service) SetPool ¶
func (s *Service) SetPool(ctx context.Context, scope string, role config.NodeRole, capacity int64) error
SetPool persists a role-specific resource budget. Zero closes admission; absent budgets fail closed. Use the same scope for a physical resource shared by multiple nodes. Reducing capacity below outstanding claims is rejected.
func (*Service) SetTarget ¶
func (s *Service) SetTarget(ctx context.Context, target Target, roles config.NodeRoles, scopes map[config.NodeRole][]string) error
SetTarget persists the currently admitted boot and explicit enabled roles. It never releases reservations from any boot. An empty role list closes new admission (unlike the config default, explicit policy cannot imply unlimited). Only the authenticated membership/control-plane reconciler may call this; worker startup must not blindly overwrite another live incarnation.
func (*Service) Supersede ¶
func (s *Service) Supersede(ctx context.Context, failed Fence, request Request, seal func(context.Context, *sql.Tx, Record) error) (Record, error)
Supersede revokes an execution without asserting its process has retired. Old capacity remains charged independently of the replacement. The trusted controller callback seals its operation and installs its route in this same transaction. An unknown outcome must retry the identical request.
type UnknownOutcome ¶
type UnknownOutcome struct{ Err error }
UnknownOutcome means a database operation did not produce a confirmed result. Reconcile using Lookup and retry the SAME immutable operation. Never assume failure means that no reservation/execution exists.
func (*UnknownOutcome) Error ¶
func (e *UnknownOutcome) Error() string
func (*UnknownOutcome) Unwrap ¶
func (e *UnknownOutcome) Unwrap() error