Documentation
¶
Overview ¶
Package approval holds the process-local registry of parked queries.
A hold is a proxy session goroutine blocked mid-statement waiting for a human. The registry is what lets the API handler on the same replica — or a LISTEN/NOTIFY message from another one — wake that goroutine up.
The registry only *delivers* decisions. It deliberately does not decide who may approve (that is the API's job, which has the user and their groups) and does not persist anything (that is the store's job, whose compare-and-set on approval_status = 'pending' is the real source of truth). Keeping those apart is what makes double-resolution safe: the DB update decides the winner, the registry just carries the news.
Index ¶
- type Decision
- type Registry
- func (r *Registry) HeldSince(queryUID uuid.UUID) (time.Time, bool)
- func (r *Registry) Pending() []uuid.UUID
- func (r *Registry) Register(queryUID uuid.UUID) (<-chan Decision, func())
- func (r *Registry) Resolve(d Decision) bool
- func (r *Registry) ResolveAll(status, reason string, by *uuid.UUID, byName string) []uuid.UUID
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Decision ¶
type Decision struct {
// QueryUID identifies the hold. The waiting session asserts this equals
// its own pending uid before acting on it: without that check, a client
// able to influence timing could have somebody else's approval released
// against its statement (TOCTOU substitution).
QueryUID uuid.UUID
// Status is one of store.ApprovalApproved / ApprovalDenied /
// ApprovalAbandoned.
Status string
// By is the resolving user, nil for system resolutions (client
// disconnect, shutdown).
By *uuid.UUID
// ByName is the resolver's display name, carried so every watcher sees
// *who* unblocked a query and not merely that it unblocked.
ByName string
// Reason is the approver-supplied justification, surfaced to the client
// in the protocol-native deny error.
Reason string
// At is when the decision was taken.
At time.Time
}
Decision is the outcome delivered to a parked session.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry tracks parked statements on this replica.
func (*Registry) Pending ¶
Pending returns the uids parked on this replica, oldest first is not guaranteed — callers use this for shutdown draining and telemetry, not ordering.
func (*Registry) Register ¶
Register parks a query. The returned channel receives at most one decision; release must be called (deferred) when the session stops waiting, whatever the reason — otherwise the hold leaks and shutdown would block on it.
func (*Registry) Resolve ¶
Resolve delivers a decision to a locally parked session. It reports whether a hold existed here — false simply means the session lives on another replica (or already gave up), which is not an error.
func (*Registry) ResolveAll ¶
ResolveAll delivers the same status to every hold on this replica and returns the uids it resolved. Used on shutdown: draining must explicitly abandon parked queries rather than hang the shutdown or, worse, silently let them through.