Documentation
¶
Overview ¶
Package extensions shares typed model ownership for framework model stores. It does not grant authentication or authorization; applications retain those decisions before invoking a model extension.
Index ¶
- func Digest(parts ...string) string
- func LoadInParts[M, S any](ctx context.Context, parents []M, size int, limit error, ...) ([]S, error)
- func Module(name foundation.ProviderID, key foundation.Key[*Store], ...) foundation.Module
- func ORMIdentity[M any, K comparable](owner Owner[M, K]) orm.ModelIdentity[M, K]
- type Config
- type Declaration
- type Owner
- func (o Owner[M, K]) ActiveSubjects(ctx context.Context, executor database.Executor, registry *Registry, ...) (map[string]bool, []string, error)
- func (o Owner[M, K]) Check(r *Registry) error
- func (o Owner[M, K]) Format(s fmt.State, _ rune)
- func (o Owner[M, K]) Lock(ctx context.Context, tx *database.Tx, registry *Registry, ...) (Subject, error)
- func (o Owner[M, K]) Name() OwnerName
- func (o Owner[M, K]) Parse(identity model.Identity) (model.Reference[M, K], error)
- func (o Owner[M, K]) RecordedModels() []string
- func (o Owner[M, K]) Registration() Declaration
- func (o Owner[M, K]) Scope() string
- func (o Owner[M, K]) StorageModel() string
- func (o Owner[M, K]) Subject(reference model.Reference[M, K]) (Subject, error)
- func (o Owner[M, K]) SubjectKey(reference model.Reference[M, K]) (string, error)
- func (o Owner[M, K]) Validate() error
- type OwnerDescription
- type OwnerName
- type OwnerOptions
- type Registry
- func (r *Registry) AdoptSubject(owner OwnerName, identity model.Identity) (Subject, error)
- func (r *Registry) DeclaresModel(owner OwnerName, name string) bool
- func (r *Registry) DeclaresScope(owner OwnerName, scope string) bool
- func (r *Registry) Owners() []OwnerName
- func (r *Registry) RetainedSubjects(ctx context.Context, executor database.Executor, owner OwnerName, ...) (map[string]bool, error)
- func (r *Registry) Scope(owner OwnerName) (string, error)
- func (r *Registry) Subject(owner OwnerName, identity model.Identity) (Subject, error)
- func (r *Registry) SubjectKey(owner OwnerName, identity model.Identity) (string, error)
- func (r *Registry) Validate() error
- type SlotBinding
- type SlotDescription
- type Store
- func (s *Store) Clock() clock.Clock
- func (s *Store) Close(ctx context.Context) error
- func (s *Store) Database() *database.DB
- func (s *Store) Done() <-chan struct{}
- func (*Store) Format(state fmt.State, _ rune)
- func (s *Store) Join(ctx context.Context, tx *database.Tx, ...) error
- func (s *Store) Now() (temporal.DateTime, error)
- func (s *Store) Read(ctx context.Context, fn func(context.Context, *database.Tx) error) error
- func (s *Store) ReadFor(ctx context.Context, executor database.Executor, ...) error
- func (s *Store) Registry() *Registry
- func (s *Store) Schema() string
- func (s *Store) Validate() error
- func (s *Store) Write(ctx context.Context, fn func(context.Context, *database.Tx) error) error
- type Subject
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Digest ¶
Digest is the shared unambiguous hashing boundary for infrastructure scopes and operation identifiers. Inputs are JSON-escaped owned strings.
func LoadInParts ¶
func LoadInParts[M, S any](ctx context.Context, parents []M, size int, limit error, load func(context.Context, []M) ([]S, error)) ([]S, error)
LoadInParts runs load over parents in parts of at most size, keeping their order. A part whose load reports limit, a store's row or byte bound, is halved and retried, so a batch bounded by retained bytes loads whenever each owner fits alone. Reads are side-effect free, so a retry repeats no effect.
func Module ¶
func Module(name foundation.ProviderID, key foundation.Key[*Store], requires []foundation.ProviderID, construct func(foundation.Resolver) (*Store, error)) foundation.Module
Module owns its Store and requires providers owning its borrowed database. Feature managers using the store must in turn depend on this module.
func ORMIdentity ¶
func ORMIdentity[M any, K comparable](owner Owner[M, K]) orm.ModelIdentity[M, K]
ORMIdentity returns the exact identity retained by a declaration-based owner. Example: extensions.ORMIdentity(owner).ReferenceOf(article).
Types ¶
type Config ¶
Config bounds the shared store. MaxActive admits that many concurrent operations; a burst beyond it queues in FIFO order for a short bounded wait before failing with fault.Overloaded, so latency spikes delay reads instead of rejecting them. Timeout bounds each admitted operation.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns default schema, clock, capacity, and operation timeout settings.
type Declaration ¶
type Declaration struct {
// contains filtered or unexported fields
}
Declaration erases model types only at application assembly. Names and model namespaces, including declared storage models, must be unique; constructing a registry performs no database I/O.
func (Declaration) Describe ¶
func (d Declaration) Describe() OwnerDescription
Describe returns the owner's persisted identity for inspection.
func (Declaration) Name ¶
func (d Declaration) Name() OwnerName
Name identifies the declared owner for assembly diagnostics.
type Owner ¶
type Owner[M any, K comparable] struct { // contains filtered or unexported fields }
Owner binds one model and its concrete key to framework identity metadata. Reuse this exact declaration across attachments, metadata and translations.
func DefineORMOwner ¶
func DefineORMOwner[M any, K comparable](name OwnerName, source orm.ModelIdentity[M, K], options OwnerOptions) Owner[M, K]
DefineORMOwner binds a declaration's identity to the existing extension stores. Pin StorageModel before renaming a table. Example: extensions.DefineORMOwner("articles",orm.IdentityOf(Articles.Table,Articles.Key()),extensions.OwnerOptions{StorageModel:"articles"}).
func (Owner[M, K]) ActiveSubjects ¶
func (o Owner[M, K]) ActiveSubjects(ctx context.Context, executor database.Executor, registry *Registry, references []model.Reference[M, K]) (map[string]bool, []string, error)
ActiveSubjects performs one bounded primary-key query for owners visible under the declared soft-delete policy. It returns active opaque Subject.Key values and each reference's subject key in input order, as SubjectKey derives it.
func (Owner[M, K]) Lock ¶
func (o Owner[M, K]) Lock(ctx context.Context, tx *database.Tx, registry *Registry, reference model.Reference[M, K]) (Subject, error)
Lock validates the exact registry declaration then locks a currently active owner. The caller's transaction serializes extension writes against owner deletion and soft deletion. Existing model snapshots alone are insufficient.
func (Owner[M, K]) Parse ¶
Parse restores a typed reference from a serialized identity. An identity attributed to the declared storage model is accepted as this owner's model: persisted rows written before a table rename keep their original attribution, while the key must still round trip through the current key codec.
func (Owner[M, K]) RecordedModels ¶
RecordedModels lists every model name persisted identities of this owner may carry: the current model, the storage model and declared previous models.
func (Owner[M, K]) Registration ¶
func (o Owner[M, K]) Registration() Declaration
Registration returns the owner's registration callbacks, or an empty declaration for an undefined owner.
func (Owner[M, K]) Scope ¶
Scope is the opaque persisted owner namespace. It depends only on the owner name and declared storage model, so a pinned storage model survives renames.
func (Owner[M, K]) StorageModel ¶
StorageModel is the declared model name of the persisted owner scope. It equals the ORM identity's model name unless OwnerOptions pins a storage identity.
func (Owner[M, K]) Subject ¶
Subject converts a typed reference into an extension subject with a JSON identity snapshot.
func (Owner[M, K]) SubjectKey ¶
SubjectKey returns the Subject.Key that Subject returns for reference, with the same validation but without snapshotting the identity. Reads use it to match owners with rows, which is all a subject key is for.
type OwnerDescription ¶
type OwnerDescription struct {
Name OwnerName `json:"name"`
Model string `json:"model"`
StorageModel string `json:"storage_model"`
}
OwnerDescription is an inspection snapshot of a registered owner identity.
type OwnerOptions ¶
OwnerOptions declares the owner's persisted identity. StorageModel is the model name recorded in the owner scope, so every stored extension row, registration key and attachment object path depends on the declared owner identity rather than the current table name. Empty uses the declared table name, which is the historical, compatible scope. Declare the previous table name here before renaming an owner table; stored identities attributed to it are then accepted and decoded through the current key codec.
PreviousModels lists model names this owner's rows were recorded under before an undeclared rename. Only rows whose recorded scope and identity name one of these, the current model or the storage model are adopted by the explicit re-scope maintenance commands; rows of any other earlier model are reported, never moved.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds validated model extension owner declarations.
func NewRegistry ¶
func NewRegistry(owners ...Declaration) (*Registry, error)
NewRegistry validates and registers up to 256 owners, rejecting overlapping names or recorded models.
func (*Registry) AdoptSubject ¶
AdoptSubject is the explicit re-scope maintenance boundary. It attributes a persisted identity recorded under one of the owner's declared models (see DeclaresModel) to its current model, decodes the key through the current codec and returns the subject in the owner's current scope. An identity of any other model is rejected. It performs no I/O and grants nothing.
func (*Registry) DeclaresModel ¶
DeclaresModel reports whether name is the owner's current model, storage model or one of its declared OwnerOptions.PreviousModels.
func (*Registry) DeclaresScope ¶
DeclaresScope reports whether scope is the owner scope of one of the owner's declared models, the scopes its persisted rows may have been written under.
func (*Registry) Owners ¶
Owners returns a copy of the sorted owner names; a nil registry returns nil.
func (*Registry) RetainedSubjects ¶
func (r *Registry) RetainedSubjects(ctx context.Context, executor database.Executor, owner OwnerName, identities []model.Identity) (map[string]bool, error)
RetainedSubjects is the explicit maintenance boundary. It includes soft- deleted owners, preventing them from being misclassified as orphans. Unknown owner declarations fail closed; maintenance never guesses a table name.
func (*Registry) Subject ¶
Subject restores a registered owner's identity at an explicit heterogeneous maintenance boundary. Ordinary model APIs retain Owner[M,K].
func (*Registry) SubjectKey ¶
SubjectKey returns the Subject.Key that Subject returns for identity, with the same validation but without snapshotting the identity.
type SlotBinding ¶
type SlotBinding[M any, K comparable, S any] struct { Field string Reference func(M) model.Reference[M, K] Get func(M) S Set func(M, S) M }
SlotBinding connects one generated model struct field to an extension declaration. Generation supplies it from the model's slot fields; Field names the Go field, which identifies the slot in eager loading and diagnostics. Reference derives the owner identity from a model value without I/O. Get and Set read and replace the slot on a model copy.
func BindSlot ¶
func BindSlot[M any, K comparable, S any](key orm.Key[M, K], slot orm.Slot[M, S]) SlotBinding[M, K, S]
BindSlot connects a validated declaration offset and primary key to an extension. Example: extensions.BindSlot(Articles.Key(),Articles.Title).
func (SlotBinding[M, K, S]) Validate ¶
func (b SlotBinding[M, K, S]) Validate() error
Validate checks the generated binding without calling its functions.
type SlotDescription ¶
type SlotDescription struct {
Field string `json:"field"`
Kind string `json:"kind"`
Name string `json:"name"`
Storage string `json:"storage"`
MaxBytes int64 `json:"max_bytes,omitempty"`
Require string `json:"require,omitempty"`
Disk string `json:"disk,omitempty"`
MaxFiles int `json:"max_files,omitempty"`
Accepted []string `json:"accepted,omitempty"`
Variants []string `json:"variants,omitempty"`
Version uint32 `json:"version,omitempty"`
}
SlotDescription is an owned, secret-free inspection snapshot of one model extension slot: its Go field, kind, stored name and declared policy bounds. Kinds are "text", "one", "many" and "value". Unused bounds are omitted.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store owns only operation admission. The database and immutable owner registry are borrowed. Constructing a store does not connect, migrate or seed data.
func New ¶
New validates dependencies and configuration and creates an extension store borrowing the database.
func (*Store) Clock ¶
Clock is the store's configured time source. Feature caches use it for expiry so tests and applications share one injected clock.
func (*Store) Close ¶
Close closes operation admission and waits for tracked work using the supplied context.
func (*Store) Done ¶
func (s *Store) Done() <-chan struct{}
Done returns the operation group's completion channel.
func (*Store) Join ¶
func (s *Store) Join(ctx context.Context, tx *database.Tx, fn func(context.Context, *database.Tx) error) error
Join contains infrastructure writes in a savepoint of this store's exact borrowed pool. It restores the caller's search_path and never commits the outer transaction. Lifecycle adapters use this for atomic owner cleanup.
func (*Store) Read ¶
Read holds one read-only repeatable snapshot across owner checks and batched extension reads. It never adds row locks or invokes model presentation hooks.
func (*Store) ReadFor ¶
func (s *Store) ReadFor(ctx context.Context, executor database.Executor, fn func(context.Context, *database.Tx) error) error
ReadFor reads inside the caller's transaction when executor is a transaction of this store's exact pool, so slot loads see that transaction's own uncommitted writes; the savepoint restores its search path. Any other executor, including custom wrappers, reads from Read's own snapshot.