Documentation
¶
Overview ¶
Package metadata stores typed, model-owned values through explicit key declarations. It shares owner identity and transactions with model extensions.
Index ¶
- Constants
- func Cleanup[M any, K comparable](ctx context.Context, tx *database.Tx, m *Manager, owner extensions.Owner[M, K], ...) error
- func CleanupIdentity(ctx context.Context, tx *database.Tx, m *Manager, owner extensions.OwnerName, ...) error
- func DeleteAll[M any, K comparable](ctx context.Context, m *Manager, owner extensions.Owner[M, K], ...) (int, error)
- func Matching[M any, K comparable, V any](ctx context.Context, manager *Manager, key Key[M, K, V], input V) (orm.Predicate[M], error)
- func Migrations() []migrate.Definition
- func PruneOrphans(ctx context.Context, m *Manager, owner extensions.OwnerName, keys []string) (int, error)
- type Batch
- type Cursor
- type Key
- func (k Key[M, K, V]) Decode(ctx context.Context, r Record[M]) (V, error)
- func (k Key[M, K, V]) Forget(ctx context.Context, m *Manager, owner model.Reference[M, K]) (bool, error)
- func (Key[M, K, V]) Format(s fmt.State, _ rune)
- func (k Key[M, K, V]) Get(ctx context.Context, m *Manager, owner model.Reference[M, K]) (value.Optional[V], error)
- func (k Key[M, K, V]) Load(ctx context.Context, m *Manager, owners []model.Reference[M, K]) (Batch[M, K, V], error)
- func (k Key[M, K, V]) Name() Name
- func (k Key[M, K, V]) Registration() Registration
- func (k Key[M, K, V]) Set(ctx context.Context, m *Manager, owner model.Reference[M, K], input V) error
- func (k Key[M, K, V]) SetIn(ctx context.Context, tx *database.Tx, m *Manager, owner model.Reference[M, K], ...) error
- func (k Key[M, K, V]) Validate() error
- func (k Key[M, K, V]) Version() Version
- type Manager
- type Name
- type Orphan
- type OrphanPage
- type Record
- func (r Record[M]) CreatedAt() temporal.DateTime
- func (r Record[M]) DynamicValue() (json.RawMessage, error)
- func (Record[M]) Format(s fmt.State, _ rune)
- func (Record[M]) MarshalJSON() ([]byte, error)
- func (r Record[M]) Name() Name
- func (r Record[M]) UpdatedAt() temporal.DateTime
- func (r Record[M]) Version() Version
- type Registration
- type RescopePage
- type Spec
- type StaleRow
- type Undeclared
- type Value
- type ValueHandle
- func (s ValueHandle[M, K, V]) Describe() extensions.SlotDescription
- func (s ValueHandle[M, K, V]) Forget(ctx context.Context, owner M) (bool, error)
- func (s ValueHandle[M, K, V]) ForgetIn(ctx context.Context, tx *database.Tx, owner M) (bool, error)
- func (ValueHandle[M, K, V]) Format(s fmt.State, _ rune)
- func (s ValueHandle[M, K, V]) From(m *Manager) ValueHandle[M, K, V]
- func (s ValueHandle[M, K, V]) Name() Name
- func (s ValueHandle[M, K, V]) Registration() Registration
- func (s ValueHandle[M, K, V]) Relation(slot orm.Slot[M, Value[V]]) orm.ExtensionRelation[M]
- func (s ValueHandle[M, K, V]) Save(ctx context.Context, owner M, input V) error
- func (s ValueHandle[M, K, V]) SaveIn(ctx context.Context, tx *database.Tx, owner M, input V) error
- func (s ValueHandle[M, K, V]) Validate() error
- type Version
Constants ¶
const ( MigrationOrigin migrate.Origin = "foundry.metadata" CreateMetadata migrate.ID = "000001_create_metadata" Introduced migrate.Version = "v0.1.0" )
const MaxBatchBytes = extensionvalue.MaxBatchBytes
const MaxKeysPerOwner = 256
const MaxValueBytes = extensionvalue.MaxBytes
Variables ¶
This section is empty.
Functions ¶
func Cleanup ¶
func Cleanup[M any, K comparable](ctx context.Context, tx *database.Tx, m *Manager, owner extensions.Owner[M, K], reference model.Reference[M, K], operation lifecycle.Operation) error
Cleanup joins a generated Deleted/ForceDeleted observer's transaction. Soft deletion keeps values for restoration; ordinary reads remain unavailable. A still-existing owner is rejected, preventing accidental early cleanup. Bulk model deletes skip observers and require explicit maintenance afterward.
func CleanupIdentity ¶
func CleanupIdentity(ctx context.Context, tx *database.Tx, m *Manager, owner extensions.OwnerName, identity model.Identity) error
CleanupIdentity is Cleanup for an owner known by its registered name and persisted identity, such as a durable cleanup job's request. It joins tx and rejects an owner that still exists.
func DeleteAll ¶
func DeleteAll[M any, K comparable](ctx context.Context, m *Manager, owner extensions.Owner[M, K], reference model.Reference[M, K]) (int, error)
DeleteAll removes metadata for an active owner. Lifecycle cleanup uses Cleanup instead, after the owner's ordinary DELETE/ForceDelete SQL has succeeded.
func Matching ¶
func Matching[M any, K comparable, V any](ctx context.Context, manager *Manager, key Key[M, K, V], input V) (orm.Predicate[M], error)
Matching materializes a bounded ORM owner predicate for an exact canonical JSON value and declared version. It uses the manager's existing matching limits, validation and cancellation. The declaration must have an ORM owner. No match produces a false predicate; the subsequent owner query retains its own fresh visibility and authorization. This is a snapshot of matching keys, not a live subquery. Example: predicate, err := metadata.Matching(ctx, manager, Preferences, input); then Owners.Query().Where(predicate).
func Migrations ¶
func Migrations() []migrate.Definition
Migrations are explicit and use the common Store's schema. No automatic boot migration or owner-table inference occurs.
func PruneOrphans ¶
func PruneOrphans(ctx context.Context, m *Manager, owner extensions.OwnerName, keys []string) (int, error)
PruneOrphans locks exact inspected row keys and rechecks current owners, including soft-deleted models. Existing and foreign rows remain untouched.
Types ¶
type Batch ¶
type Batch[M any, K comparable, V any] struct { // contains filtered or unexported fields }
Batch is an immutable snapshot of one typed key for currently active owners. Decode returns fresh values. It is not an authorization or eligibility cache for later operations; each new read/write rechecks the actual owner.
func (Batch[M, K, V]) Get ¶
func (b Batch[M, K, V]) Get(ctx context.Context, owner model.Reference[M, K]) (value.Optional[V], error)
Get decodes a fresh value from the loaded snapshot without I/O. It returns database.NotFound for an owner absent from the active set and an unset optional for a missing key.
type Cursor ¶
type Cursor = extensionmaintenance.Cursor
Cursor resumes a bounded scan for this feature and registered owner. It is not a capability or a stable snapshot across separate pages.
type Key ¶
type Key[M any, K comparable, V any] struct { // contains filtered or unexported fields }
Key retains both the owner model/key and the value codec. Reuse the same declaration in assembly and calls; a matching string name cannot substitute an unrelated value type or schema. Increment Version for incompatible changes.
func Define ¶
func Define[M any, K comparable, V any](owner extensions.Owner[M, K], name Name, version Version, schema contract.JSON[V]) Key[M, K, V]
Define declares an owner-bound, versioned metadata key with the supplied JSON contract. The returned declaration retains its identity for registration; validation is deferred.
func KeyOf ¶
func KeyOf[M any, K comparable, V any](slot ValueHandle[M, K, V]) Key[M, K, V]
KeyOf returns the slot's existing key for explicit batch reads and matching. It preserves registration identity and the concrete value type; a zero handle returns an invalid zero key. Example: metadata.KeyOf(bound.SEO).Get(ctx,manager,reference).
func (Key[M, K, V]) Decode ¶
Decode checks the record's owner scope, name and version against the key, then decodes its value.
func (Key[M, K, V]) Forget ¶
func (k Key[M, K, V]) Forget(ctx context.Context, m *Manager, owner model.Reference[M, K]) (bool, error)
Forget locks the active owner and removes its value in the manager's transaction. It reports whether a stored value was removed.
func (Key[M, K, V]) Get ¶
func (k Key[M, K, V]) Get(ctx context.Context, m *Manager, owner model.Reference[M, K]) (value.Optional[V], error)
Get loads and decodes this key for one owner. A missing key is unset; an inactive owner returns database.NotFound.
func (Key[M, K, V]) Load ¶
func (k Key[M, K, V]) Load(ctx context.Context, m *Manager, owners []model.Reference[M, K]) (Batch[M, K, V], error)
Load reads this key for the supplied owners into a bounded snapshot, checking stored versions and values.
func (Key[M, K, V]) Registration ¶
func (k Key[M, K, V]) Registration() Registration
Registration returns the key's manager registration, or a zero registration for a zero key.
func (Key[M, K, V]) Set ¶
func (k Key[M, K, V]) Set(ctx context.Context, m *Manager, owner model.Reference[M, K], input V) error
Set validates and stores input for an active owner in the manager's transaction. It replaces an existing value and locks the owner before writing.
func (Key[M, K, V]) SetIn ¶
func (k Key[M, K, V]) SetIn(ctx context.Context, tx *database.Tx, m *Manager, owner model.Reference[M, K], input V) error
SetIn joins a business transaction through the common savepoint/schema helper. A suppressed error cannot leave a partial metadata write in the outer Tx.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager borrows the common Store; it has no independent background work or shutdown. The store bounds and owns every metadata operation's actual lifetime.
func New ¶
func New(store *extensions.Store, keys ...Registration) (*Manager, error)
New validates registrations and returns a manager borrowing store. Duplicate owner-scoped key names return fault.Duplicate; no database I/O occurs.
type OrphanPage ¶
OrphanPage contains orphan matches, the number of rows scanned and a continuation cursor.
func InspectOrphans ¶
func InspectOrphans(ctx context.Context, m *Manager, owner extensions.OwnerName, cursor Cursor, limit int) (OrphanPage, error)
InspectOrphans never deletes. The limit bounds scanned rows, not matches, so sparse orphan sets cannot repeatedly starve later rows.
type Record ¶
type Record[M any] struct { // contains filtered or unexported fields }
Record preserves model ownership while supporting deliberate administrative inspection. Decode through its matching typed Key, or explicitly export the dynamic value. Records do not implicitly serialize private metadata.
func All ¶
func All[M any, K comparable](ctx context.Context, m *Manager, owner extensions.Owner[M, K], reference model.Reference[M, K]) ([]Record[M], error)
All returns the bounded complete value set for one active owner. It includes unregistered persisted keys for explicit migration/administrative inspection.
func (Record[M]) DynamicValue ¶
func (r Record[M]) DynamicValue() (json.RawMessage, error)
DynamicValue decodes a fresh JSON representation for explicit administrative inspection.
func (Record[M]) MarshalJSON ¶
MarshalJSON returns fault.Invalid to prevent implicit metadata disclosure.
type Registration ¶
type Registration struct {
// contains filtered or unexported fields
}
Registration retains a key declaration's identity and validation for manager assembly.
type RescopePage ¶
type RescopePage = extensionmaintenance.RescopePage
RescopePage reports a bounded stale-scope inspection or move, including conflicts and continuation.
func InspectStale ¶
func InspectStale(ctx context.Context, m *Manager, owner extensions.OwnerName, cursor Cursor, limit int) (RescopePage, error)
InspectStale lists, without writing, rows whose owner column names this registered owner but whose scope is not the owner's current scope. They are invisible to ordinary reads, typically after an owner table was renamed without declaring extensions.OwnerOptions.StorageModel; declare the old name in OwnerOptions.PreviousModels to adopt them. Conflicts, Missing subjects and Undeclared models are reported and left in place.
func Rescope ¶
func Rescope(ctx context.Context, m *Manager, owner extensions.OwnerName, cursor Cursor, limit int) (RescopePage, error)
Rescope moves one bounded page of stale rows into the owner's current scope, preserving name, version, value and creation time. Each row is verified and locked first; a conflicting current-scope row is never overwritten.
type Spec ¶
Spec declares a metadata slot's stored version and JSON contract. A zero Version selects 1 and a zero JSON selects the contract generation inferred from the slot's value type (a generated DTO, scalar or json.RawMessage). Increment Version for incompatible changes: strict decoding rejects stored values with removed or renamed fields.
type StaleRow ¶
type StaleRow = extensionmaintenance.Stale
StaleRow is one metadata row recorded under an earlier scope of its owner and its key in the owner's current scope. RescopePage lists rows inspected or moved; Conflicts are stale rows whose current-scope key already exists.
type Undeclared ¶
type Undeclared = extensionmaintenance.Undeclared
Undeclared lists stored names that no current registration declares.
func InspectUndeclared ¶
func InspectUndeclared(ctx context.Context, m *Manager, owner extensions.OwnerName) (Undeclared, error)
InspectUndeclared lists stored key names in owner's current scope that no key registered with m declares, for example after renaming a slot field without pinning its stored name. It reads names only and modifies nothing.
type Value ¶
type Value[V any] struct { // contains filtered or unexported fields }
Value is a model slot holding one typed metadata value. The zero value is not loaded; a loaded slot distinguishes an absent key from a stored value. Reading a slot performs no I/O. Maps and slices inside a decoded value keep ordinary Go value-copy semantics.
func (Value[V]) MarshalJSON ¶
MarshalJSON returns fault.Invalid to prevent implicit metadata disclosure.
type ValueHandle ¶
type ValueHandle[M any, K comparable, V any] struct { // contains filtered or unexported fields }
ValueHandle retains typed slot capabilities behind shared callback state. Example: slot.From(manager).Relation(Fields.Slot).
func ValueOf ¶
func ValueOf[M any, K comparable, V any](owner extensions.Owner[M, K], name Name, spec Spec[V], inferred contract.JSON[V], binding extensions.SlotBinding[M, K, Value[V]]) ValueHandle[M, K, V]
ValueOf declares a thin metadata handle retaining the concrete input and JSON contract. Example: metadata.ValueOf(owner,"seo",spec,contract.StringJSON[string](),binding).
func (ValueHandle[M, K, V]) Describe ¶
func (s ValueHandle[M, K, V]) Describe() extensions.SlotDescription
Describe returns an owned inspection snapshot. Example: slot.Describe().
func (ValueHandle[M, K, V]) Forget ¶
func (s ValueHandle[M, K, V]) Forget(ctx context.Context, owner M) (bool, error)
Forget removes the stored value and reports whether it existed. Example: slot.Forget(ctx,article).
func (ValueHandle[M, K, V]) ForgetIn ¶
ForgetIn removes the stored value in the caller transaction. Example: slot.ForgetIn(ctx,tx,article).
func (ValueHandle[M, K, V]) Format ¶
func (ValueHandle[M, K, V]) Format(s fmt.State, _ rune)
Format omits retained runtime state. Example: fmt.Sprintf("%+v",slot).
func (ValueHandle[M, K, V]) From ¶
func (s ValueHandle[M, K, V]) From(m *Manager) ValueHandle[M, K, V]
From returns a copy borrowing this family's manager; nil leaves it unbound. Example: slot.From(manager).
func (ValueHandle[M, K, V]) Name ¶
func (s ValueHandle[M, K, V]) Name() Name
Name returns the stored name. Example: slot.Name().
func (ValueHandle[M, K, V]) Registration ¶
func (s ValueHandle[M, K, V]) Registration() Registration
Registration returns the existing manager registration. Example: slot.Registration().
func (ValueHandle[M, K, V]) Relation ¶
func (s ValueHandle[M, K, V]) Relation(slot orm.Slot[M, Value[V]]) orm.ExtensionRelation[M]
Relation binds the loader to its concrete ORM field; mismatched fields fail validation. Example: Articles.Query().With(slot.Relation(Articles.SEO)).
func (ValueHandle[M, K, V]) Save ¶
func (s ValueHandle[M, K, V]) Save(ctx context.Context, owner M, input V) error
Save replaces the typed value in the manager transaction. Example: slot.Save(ctx,article,input).
func (ValueHandle[M, K, V]) SaveIn ¶
SaveIn replaces the typed value in the caller transaction. Example: slot.SaveIn(ctx,tx,article,input).
func (ValueHandle[M, K, V]) Validate ¶
func (s ValueHandle[M, K, V]) Validate() error
Validate checks the declaration and slot binding. Example: slot.Validate().