Documentation
¶
Overview ¶
Package attachments owns typed model collections and recoverable storage workflows. Applications declare policy once and pass typed owner references.
Index ¶
- Constants
- Variables
- 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 Matching[M any, K comparable](ctx context.Context, manager *Manager, collection Collection[M, K]) (orm.Predicate[M], error)
- func Migrations() []migrate.Definition
- func Module(name foundation.ProviderID, key foundation.Key[*Manager], ...) foundation.Module
- type Attachment
- type Batch
- type BeforeContext
- type Cardinality
- type ChangeResult
- type Collection
- func (c Collection[M, K]) Add(ctx context.Context, m *Manager, owner model.Reference[M, K], upload Upload) (Result[M, K], error)
- func (c Collection[M, K]) AddFromURL(ctx context.Context, m *Manager, owner model.Reference[M, K], ...) (Result[M, K], error)
- func (c Collection[M, K]) AddIn(ctx context.Context, tx *database.Tx, m *Manager, owner model.Reference[M, K], ...) (Result[M, K], error)
- func (c Collection[M, K]) Clear(ctx context.Context, m *Manager, owner model.Reference[M, K]) (ChangeResult, error)
- func (c Collection[M, K]) Detach(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (ChangeResult, error)
- func (c Collection[M, K]) DetachKeepFile(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (RetainResult, error)
- func (c Collection[M, K]) Discard(ctx context.Context, m *Manager, prepared Prepared[M, K]) error
- func (c Collection[M, K]) Find(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (Attachment[M, K], error)
- func (c Collection[M, K]) First(ctx context.Context, m *Manager, owner model.Reference[M, K]) (value.Optional[Attachment[M, K]], error)
- func (c Collection[M, K]) ForLocale(locale i18n.LocaleID) Collection[M, K]
- func (Collection[M, K]) Format(s fmt.State, _ rune)
- func (c Collection[M, K]) Image(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M], ...) (imaging.Result, error)
- func (c Collection[M, K]) List(ctx context.Context, m *Manager, owner model.Reference[M, K]) ([]Attachment[M, K], error)
- func (c Collection[M, K]) Load(ctx context.Context, m *Manager, owners []model.Reference[M, K]) (Batch[M, K], error)
- func (c Collection[M, K]) LoadLocalized(ctx context.Context, m *Manager, owners []model.Reference[M, K]) (LocalizedBatch[M, K], error)
- func (c Collection[M, K]) Name() Name
- func (c Collection[M, K]) Open(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (io.ReadCloser, Attachment[M, K], error)
- func (c Collection[M, K]) Prepare(ctx context.Context, m *Manager, owner model.Reference[M, K], upload Upload) (Prepared[M, K], error)
- func (c Collection[M, K]) PublicURL(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (string, error)
- func (c Collection[M, K]) PublicURLOf(ctx context.Context, m *Manager, file Attachment[M, K]) (string, error)
- func (c Collection[M, K]) PublicURLsOf(ctx context.Context, m *Manager, files []Attachment[M, K]) ([]string, error)
- func (c Collection[M, K]) ReadBytes(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M], ...) ([]byte, error)
- func (c Collection[M, K]) RegenerateVariants(ctx context.Context, m *Manager, options RegenerationOptions) (RegenerationPage, error)
- func (c Collection[M, K]) Registration() Registration
- func (c Collection[M, K]) Reorder(ctx context.Context, m *Manager, owner model.Reference[M, K], order []ID[M]) ([]Attachment[M, K], error)
- func (c Collection[M, K]) Replace(ctx context.Context, m *Manager, owner model.Reference[M, K], upload Upload) (Result[M, K], error)
- func (c Collection[M, K]) ReplaceIn(ctx context.Context, tx *database.Tx, m *Manager, owner model.Reference[M, K], ...) (Result[M, K], error)
- func (c Collection[M, K]) Resolve(ctx context.Context, m *Manager, owner model.Reference[M, K], ...) (value.Optional[Resolved[M, K]], error)
- func (c Collection[M, K]) SetProperties(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M], ...) (Attachment[M, K], error)
- func (c Collection[M, K]) TemporaryURL(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M], ...) (storage.TemporaryURL, error)
- func (c Collection[M, K]) TemporaryURLOf(ctx context.Context, m *Manager, file Attachment[M, K], ...) (storage.TemporaryURL, error)
- func (c Collection[M, K]) Validate() error
- func (c Collection[M, K]) VariantPublicURLOf(ctx context.Context, m *Manager, file Attachment[M, K], variant Variant) (string, error)
- func (c Collection[M, K]) VariantTemporaryURLOf(ctx context.Context, m *Manager, file Attachment[M, K], variant Variant, ...) (storage.TemporaryURL, error)
- func (c Collection[M, K]) WithReconciliation(queue Queue) Collection[M, K]
- func (c Collection[M, K]) WithVariantQueue(queue VariantQueue) Collection[M, K]
- type Config
- type Cursor
- type Dependencies
- type File
- func (f File[M]) Collection() Name
- func (f File[M]) CreatedAt() temporal.DateTime
- func (f File[M]) EmailAttachment() (email.Attachment, error)
- func (File[M]) Format(s fmt.State, _ rune)
- func (f File[M]) ID() ID[M]
- func (f File[M]) Info() UploadInfo
- func (f File[M]) IsZero() bool
- func (f File[M]) Locale() value.Optional[i18n.LocaleID]
- func (File[M]) MarshalJSON() ([]byte, error)
- func (f File[M]) Position() int32
- func (f File[M]) Properties() (json.RawMessage, error)
- func (f File[M]) Variant(variant Variant) (VariantInfo, bool)
- func (f File[M]) Variants() []VariantInfo
- type FileOf
- type FileSource
- type Hook
- type ID
- type LocalizedBatch
- type LocalizedFiles
- type Manager
- func (m *Manager) Close(ctx context.Context) error
- func (m *Manager) Done() <-chan struct{}
- func (m *Manager) GenerateVariants(ctx context.Context, id OperationID) error
- func (m *Manager) Inspect(ctx context.Context, id OperationID) (ReconcileResult, error)
- func (m *Manager) InspectOrphans(ctx context.Context, owner extensions.OwnerName, cursor Cursor, limit int) (OrphanPage, error)
- func (m *Manager) InspectStorage(ctx context.Context, options StorageInspection) (StorageOrphanPage, error)
- func (m *Manager) PruneOrphans(ctx context.Context, owner extensions.OwnerName, ids []OperationID, ...) (ChangeResult, error)
- func (m *Manager) Reconcile(ctx context.Context, id OperationID) (ReconcileResult, error)
- func (m *Manager) ReconcilePending(ctx context.Context, limit int) ([]ReconcileResult, error)
- func (m *Manager) RegenerateVariants(ctx context.Context, owner extensions.OwnerName, collection Name, ...) (RegenerationPage, error)
- func (m *Manager) RetainedObject(ctx context.Context, id OperationID) (RetainedFile, error)
- func (m *Manager) Settle(ctx context.Context, id OperationID, settlement Settlement, queue *Queue) (ReconcileResult, error)
- func (m *Manager) Validate() error
- type Many
- type ManyHandle
- func (s ManyHandle[M, K]) Accepts(ctx context.Context, file FileSource) (bool, error)
- func (s ManyHandle[M, K]) Add(ctx context.Context, owner M, upload Upload) (Result[M, K], error)
- func (s ManyHandle[M, K]) AddFile(ctx context.Context, owner M, file FileSource) (Result[M, K], error)
- func (s ManyHandle[M, K]) AddIn(ctx context.Context, tx *database.Tx, owner M, prepared Prepared[M, K]) (Result[M, K], error)
- func (s ManyHandle[M, K]) Clear(ctx context.Context, owner M) (ChangeResult, error)
- func (s ManyHandle[M, K]) Describe() extensions.SlotDescription
- func (s ManyHandle[M, K]) Detach(ctx context.Context, owner M, id ID[M]) (ChangeResult, error)
- func (s ManyHandle[M, K]) Discard(ctx context.Context, prepared Prepared[M, K]) error
- func (ManyHandle[M, K]) Format(s fmt.State, _ rune)
- func (s ManyHandle[M, K]) From(m *Manager) ManyHandle[M, K]
- func (s ManyHandle[M, K]) Name() Name
- func (s ManyHandle[M, K]) Prepare(ctx context.Context, owner M, upload Upload) (Prepared[M, K], error)
- func (s ManyHandle[M, K]) PrepareFile(ctx context.Context, owner M, file FileSource) (Prepared[M, K], error)
- func (s ManyHandle[M, K]) PublicURLs(ctx context.Context, owner M) ([]string, error)
- func (s ManyHandle[M, K]) Registration() Registration
- func (s ManyHandle[M, K]) Relation(slot orm.Slot[M, Many[M]]) orm.ExtensionRelation[M]
- func (s ManyHandle[M, K]) Reorder(ctx context.Context, owner M, order []ID[M]) ([]Attachment[M, K], error)
- func (s ManyHandle[M, K]) Replace(ctx context.Context, owner M, upload Upload) (Result[M, K], error)
- func (s ManyHandle[M, K]) ReplaceFile(ctx context.Context, owner M, file FileSource) (Result[M, K], error)
- func (s ManyHandle[M, K]) ReplaceIn(ctx context.Context, tx *database.Tx, owner M, prepared Prepared[M, K]) (Result[M, K], error)
- func (s ManyHandle[M, K]) TemporaryURL(ctx context.Context, owner M, file File[M], options storage.LinkOptions) (storage.TemporaryURL, error)
- func (s ManyHandle[M, K]) URL(ctx context.Context, owner M, file File[M]) (string, error)
- func (s ManyHandle[M, K]) Validate() error
- func (s ManyHandle[M, K]) VariantURL(ctx context.Context, owner M, file File[M], variant Variant) (string, error)
- type Name
- type One
- type OneHandle
- func (s OneHandle[M, K]) Accepts(ctx context.Context, file FileSource) (bool, error)
- func (s OneHandle[M, K]) Clear(ctx context.Context, owner M) (ChangeResult, error)
- func (s OneHandle[M, K]) Describe() extensions.SlotDescription
- func (s OneHandle[M, K]) Detach(ctx context.Context, owner M, id ID[M]) (ChangeResult, error)
- func (s OneHandle[M, K]) Discard(ctx context.Context, prepared Prepared[M, K]) error
- func (OneHandle[M, K]) Format(s fmt.State, _ rune)
- func (s OneHandle[M, K]) From(m *Manager) OneHandle[M, K]
- func (s OneHandle[M, K]) Name() Name
- func (s OneHandle[M, K]) Prepare(ctx context.Context, owner M, upload Upload) (Prepared[M, K], error)
- func (s OneHandle[M, K]) PrepareFile(ctx context.Context, owner M, file FileSource) (Prepared[M, K], error)
- func (s OneHandle[M, K]) PublicURL(ctx context.Context, owner M) (value.Optional[string], error)
- func (s OneHandle[M, K]) Registration() Registration
- func (s OneHandle[M, K]) Relation(slot orm.Slot[M, One[M]]) orm.ExtensionRelation[M]
- func (s OneHandle[M, K]) Replace(ctx context.Context, owner M, upload Upload) (Result[M, K], error)
- func (s OneHandle[M, K]) ReplaceFile(ctx context.Context, owner M, file FileSource) (Result[M, K], error)
- func (s OneHandle[M, K]) ReplaceIn(ctx context.Context, tx *database.Tx, owner M, prepared Prepared[M, K]) (Result[M, K], error)
- func (s OneHandle[M, K]) TemporaryURL(ctx context.Context, owner M, file File[M], options storage.LinkOptions) (storage.TemporaryURL, error)
- func (s OneHandle[M, K]) URL(ctx context.Context, owner M, file File[M]) (string, error)
- func (s OneHandle[M, K]) Validate() error
- func (s OneHandle[M, K]) VariantURL(ctx context.Context, owner M, file File[M], variant Variant) (string, error)
- type Operation
- type OperationID
- type Orphan
- type OrphanPage
- type Policy
- type Prepared
- type Publication
- type Queue
- type ReconcileJob
- type ReconcileRequest
- type ReconcileResult
- type RegenerationCursor
- type RegenerationOptions
- type RegenerationPage
- type Registration
- type RemoteSource
- type Resolved
- type Result
- type RetainResult
- type RetainedFile
- type Settlement
- type State
- type StorageCursor
- type StorageInspection
- type StorageOrphanPage
- type Undeclared
- type Upload
- type UploadInfo
- type Variant
- type VariantInfo
- type VariantJob
- type VariantName
- type VariantQueue
- type VariantRequest
- type VariantState
Constants ¶
const ( MaxUploadBytes int64 = 64 << 20 MaxCollectionFiles = 256 MaxOwnerIntents = 4096 MaxPropertiesBytes = 64 << 10 )
const ( DefaultMaxReads = 64 DefaultSettleAfter = 15 * time.Minute // MaxOwnerCleanup bounds concurrent owner-delete observers per manager. MaxOwnerCleanup = 4096 )
const ( MigrationOrigin migrate.Origin = "foundry.attachments" CreateAttachments migrate.ID = "000001_create_attachments" CreateVariants migrate.ID = "000002_create_variants" Introduced migrate.Version = "v0.1.0" )
const ( MaxBatchFiles = 4096 MaxBatchPropertiesBytes = 4 << 20 )
const MaxRegenerationBatch = 100
const (
// MaxVariants bounds declared variants per collection.
MaxVariants = 8
)
Variables ¶
var ActiveContentRefused = safeerror.Sentinel(fault.Invalid, "script-capable attachment cannot be linked inline")
ActiveContentRefused reports an inline link to a script-capable attachment (SVG, HTML, XML, JavaScript) whose policy does not set InlineActiveContent. It matches fault.Invalid.
VariantUnavailable reports a declared variant that has not been generated (yet) for an attachment, for example while its job is queued. It matches fault.Missing.
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, queue *Queue) error
Cleanup joins a generated owner's transactional Deleted/ForceDeleted observer. Soft deletion preserves files for restoration. Ready/stored ownership changes and optional job outbox rows roll back with the owner. Writing/uncertain intents remain visible for settlement; they cannot be deleted based on owner absence.
func CleanupIdentity ¶
func CleanupIdentity(ctx context.Context, tx *database.Tx, m *Manager, owner extensions.OwnerName, identity model.Identity, queue *Queue) 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, rejects an owner that still exists and deletes stored objects after commit.
func Matching ¶
func Matching[M any, K comparable](ctx context.Context, manager *Manager, collection Collection[M, K]) (orm.Predicate[M], error)
Matching materializes a bounded ORM owner predicate for ready attachments in the collection and exact locale. 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 := attachments.Matching(ctx, manager, Avatar.ForLocale("en")); then Owners.Query().Where(predicate).
func Migrations ¶
func Migrations() []migrate.Definition
func Module ¶
func Module(name foundation.ProviderID, key foundation.Key[*Manager], requires []foundation.ProviderID, construct func(foundation.Resolver) (*Manager, error)) foundation.Module
Module owns the manager and requires providers owning its borrowed store, disks, image engine and locale catalog. Workers invoking it must stop first.
Types ¶
type Attachment ¶
type Attachment[M any, K comparable] struct { File[M] // contains filtered or unexported fields }
Attachment is a ready File with its typed owner reference.
func (Attachment[M, K]) MarshalJSON ¶
func (Attachment[M, K]) MarshalJSON() ([]byte, error)
func (Attachment[M, K]) Owner ¶
func (a Attachment[M, K]) Owner() model.Reference[M, K]
type Batch ¶
type Batch[M any, K comparable] struct { // contains filtered or unexported fields }
type BeforeContext ¶
type BeforeContext[M any, K comparable] struct { Owner model.Reference[M, K] Collection Name Locale value.Optional[i18n.LocaleID] Upload UploadInfo }
BeforeContext contains detected metadata, not the caller-owned reader or a mutable image buffer. The application can authorize through Owner.Key().
type ChangeResult ¶
type ChangeResult struct {
Publication Publication
Affected int
PendingCleanup []OperationID
}
type Collection ¶
type Collection[M any, K comparable] struct { // contains filtered or unexported fields }
func Define ¶
func Define[M any, K comparable](owner extensions.Owner[M, K], name Name, policy Policy, hooks ...Hook[M, K]) Collection[M, K]
func ManyCollection ¶
func ManyCollection[M any, K comparable](slot ManyHandle[M, K]) Collection[M, K]
ManyCollection returns the multiple-slot declaration for explicit batch reads and matching. It preserves registration identity and policy; a zero handle returns an invalid zero collection. Example: attachments.ManyCollection(bound.Gallery).List(ctx,manager,reference).
func OneCollection ¶
func OneCollection[M any, K comparable](slot OneHandle[M, K]) Collection[M, K]
OneCollection returns the single-slot declaration for explicit collection operations. It preserves registration identity and policy; a zero handle returns an invalid zero collection. Example: attachments.OneCollection(bound.Logo).List(ctx,manager,reference).
func (Collection[M, K]) Add ¶
func (c Collection[M, K]) Add(ctx context.Context, m *Manager, owner model.Reference[M, K], upload Upload) (Result[M, K], error)
Add appends to a multiple collection and replaces a single collection.
func (Collection[M, K]) AddFromURL ¶
func (c Collection[M, K]) AddFromURL(ctx context.Context, m *Manager, owner model.Reference[M, K], source RemoteSource) (Result[M, K], error)
AddFromURL downloads one remote file within the collection's MaxBytes and adds it exactly like Add. Acceptance is detected from the downloaded bytes; the response Content-Type is only a hint. Redirects and non-2xx responses fail without adding a file. Manager admission covers the complete download, validation, storage and publication, retaining one bounded input buffer. Image processing remains subject to the image engine's separate limits.
func (Collection[M, K]) AddIn ¶
func (c Collection[M, K]) AddIn(ctx context.Context, tx *database.Tx, m *Manager, owner model.Reference[M, K], prepared Prepared[M, K]) (Result[M, K], error)
AddIn publishes a prepared upload into owner's collection inside tx, a transaction of the extension store's pool, using only that transaction: the owner may be one tx created, and the attachment becomes visible when tx commits. A failure, including a rollback, leaves the prepared upload for Discard or ReconcilePending. Old-object cleanup and unqueued variant generation run after tx commits; their failure is the transaction's after-commit error and leaves work for ReconcilePending.
func (Collection[M, K]) Clear ¶
func (c Collection[M, K]) Clear(ctx context.Context, m *Manager, owner model.Reference[M, K]) (ChangeResult, error)
func (Collection[M, K]) Detach ¶
func (c Collection[M, K]) Detach(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (ChangeResult, error)
func (Collection[M, K]) DetachKeepFile ¶
func (c Collection[M, K]) DetachKeepFile(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (RetainResult, error)
DetachKeepFile removes collection membership without deleting storage. The durable retained state survives owner deletion and ordinary orphan pruning.
func (Collection[M, K]) Discard ¶
Discard reclaims a prepared upload that will not be published, instead of leaving it to ReconcilePending. A published upload is refused and kept.
func (Collection[M, K]) Find ¶
func (c Collection[M, K]) Find(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (Attachment[M, K], error)
func (Collection[M, K]) First ¶
func (c Collection[M, K]) First(ctx context.Context, m *Manager, owner model.Reference[M, K]) (value.Optional[Attachment[M, K]], error)
func (Collection[M, K]) ForLocale ¶
func (c Collection[M, K]) ForLocale(locale i18n.LocaleID) Collection[M, K]
func (Collection[M, K]) List ¶
func (c Collection[M, K]) List(ctx context.Context, m *Manager, owner model.Reference[M, K]) ([]Attachment[M, K], error)
func (Collection[M, K]) LoadLocalized ¶
func (c Collection[M, K]) LoadLocalized(ctx context.Context, m *Manager, owners []model.Reference[M, K]) (LocalizedBatch[M, K], error)
func (Collection[M, K]) Name ¶
func (c Collection[M, K]) Name() Name
func (Collection[M, K]) Open ¶
func (c Collection[M, K]) Open(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (io.ReadCloser, Attachment[M, K], error)
Open streams an attachment pinned to its stored ETag/version. The full SHA-256 and length are verified at EOF (by the disk when the stored checksum matches the pin, otherwise here). Only the lookup uses manager read admission; the returned reader holds one disk stream slot until Close. Always close it, and close it before closing the disk.
func (Collection[M, K]) Prepare ¶
func (c Collection[M, K]) Prepare(ctx context.Context, m *Manager, owner model.Reference[M, K], upload Upload) (Prepared[M, K], error)
Prepare reads, checks and stores upload for owner's collection without publishing it, in the manager's own transactions. Call it before the transaction that publishes it begins, so that transaction needs only its own connection and sees the stored upload. An existing owner is locked while the upload is recorded, keeping its intent bound exact; owner may also be a model the publishing transaction creates, with its key chosen beforehand. On an error the returned value names any recorded intent.
func (Collection[M, K]) PublicURL ¶
func (c Collection[M, K]) PublicURL(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M]) (string, error)
PublicURL rechecks ready membership, then derives the public URL of the pinned object. Keys are immutable per upload, so no storage request is made.
func (Collection[M, K]) PublicURLOf ¶
func (c Collection[M, K]) PublicURLOf(ctx context.Context, m *Manager, file Attachment[M, K]) (string, error)
PublicURLOf derives the public URL of an attachment already loaded through this collection (for example from Load or List) without database or storage I/O. Authorize access to the attachment first; the URL does not.
func (Collection[M, K]) PublicURLsOf ¶
func (c Collection[M, K]) PublicURLsOf(ctx context.Context, m *Manager, files []Attachment[M, K]) ([]string, error)
PublicURLsOf maps loaded attachments to public URLs in order, for listing responses. It performs no database or storage I/O.
func (Collection[M, K]) RegenerateVariants ¶
func (c Collection[M, K]) RegenerateVariants(ctx context.Context, m *Manager, options RegenerationOptions) (RegenerationPage, error)
RegenerateVariants processes one batch of this collection's ready attachments in ID order under one write admission slot.
func (Collection[M, K]) Registration ¶
func (c Collection[M, K]) Registration() Registration
func (Collection[M, K]) Reorder ¶
func (c Collection[M, K]) Reorder(ctx context.Context, m *Manager, owner model.Reference[M, K], order []ID[M]) ([]Attachment[M, K], error)
Reorder accepts an exact permutation of current ready collection IDs. No omission, duplicate or foreign ID can partially change the stored ordering.
func (Collection[M, K]) Replace ¶
func (c Collection[M, K]) Replace(ctx context.Context, m *Manager, owner model.Reference[M, K], upload Upload) (Result[M, K], error)
Replace atomically replaces the complete collection membership. Old objects are eligible for cleanup only after this ownership transaction commits.
func (Collection[M, K]) ReplaceIn ¶
func (c Collection[M, K]) ReplaceIn(ctx context.Context, tx *database.Tx, m *Manager, owner model.Reference[M, K], prepared Prepared[M, K]) (Result[M, K], error)
ReplaceIn publishes a prepared upload as owner's complete collection inside tx; see AddIn.
func (Collection[M, K]) SetProperties ¶
func (c Collection[M, K]) SetProperties(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M], properties value.JSON[json.RawMessage]) (Attachment[M, K], error)
SetProperties replaces explicit dynamic object metadata, never storage pins, owner identity or collection policy.
func (Collection[M, K]) TemporaryURL ¶
func (c Collection[M, K]) TemporaryURL(ctx context.Context, m *Manager, owner model.Reference[M, K], id ID[M], expires time.Duration) (storage.TemporaryURL, error)
TemporaryURL rechecks ready membership, then signs a read link pinned to the stored version. Signing performs no storage request.
func (Collection[M, K]) TemporaryURLOf ¶
func (c Collection[M, K]) TemporaryURLOf(ctx context.Context, m *Manager, file Attachment[M, K], options storage.LinkOptions) (storage.TemporaryURL, error)
TemporaryURLOf signs a read link for a loaded attachment, pinned to its stored version, without database or storage I/O. options.Version must be zero; response overrides (for example a download Content-Disposition using the original name) are signed into the link.
func (Collection[M, K]) Validate ¶
func (c Collection[M, K]) Validate() error
func (Collection[M, K]) VariantPublicURLOf ¶
func (c Collection[M, K]) VariantPublicURLOf(ctx context.Context, m *Manager, file Attachment[M, K], variant Variant) (string, error)
VariantPublicURLOf derives the public URL of a generated variant of a loaded attachment without database or storage I/O. It fails with VariantUnavailable until the variant has been generated.
func (Collection[M, K]) VariantTemporaryURLOf ¶
func (c Collection[M, K]) VariantTemporaryURLOf(ctx context.Context, m *Manager, file Attachment[M, K], variant Variant, options storage.LinkOptions) (storage.TemporaryURL, error)
VariantTemporaryURLOf signs a read link for a generated variant, pinned to its stored version, without database or storage I/O.
func (Collection[M, K]) WithReconciliation ¶
func (c Collection[M, K]) WithReconciliation(queue Queue) Collection[M, K]
WithReconciliation binds ordinary job/outbox publication after service assembly without changing this collection's registered policy or identity.
func (Collection[M, K]) WithVariantQueue ¶
func (c Collection[M, K]) WithVariantQueue(queue VariantQueue) Collection[M, K]
WithVariantQueue generates this collection's variants through the queued job instead of synchronously after each upload. It does not change the collection's registered policy or identity.
type Config ¶
type Config struct {
MaxActive int
MaxReads int
Timeout time.Duration
CleanupTimeout time.Duration
StoredGrace time.Duration
SettleAfter time.Duration
}
Config bounds manager work. MaxActive admits uploads and other mutations, including the complete remote download, validation and persistence lifetime; MaxReads separately admits loads, lookups, reads and link signing, so a burst of reads cannot starve writes (or the reverse). Both queue briefly (at most min(Timeout, 5s)) before failing as retryable overload. Owner-delete cleanup joined from model observers uses its own MaxOwnerCleanup pool so it does not compete with application reads/writes. SettleAfter is added to a disk's operation Timeout before ReconcilePending may inspect an unresolved write. Zero MaxReads or SettleAfter selects its default.
func DefaultConfig ¶
func DefaultConfig() Config
type Cursor ¶
type Cursor = extensionmaintenance.Cursor
type Dependencies ¶
type Dependencies struct {
Store *extensions.Store
Disks *storage.Registry
Image *imaging.Engine
Locales i18n.LocaleCatalog
}
Dependencies are borrowed. Image and Locales are required only by collections that use them. Their owners must outlive this manager's actual operations.
type File ¶
type File[M any] struct { // contains filtered or unexported fields }
File is the owner-free view of one ready attachment: identity, collection, detected metadata, properties and ready variants. Model slots hold Files; Attachment adds the typed owner reference.
func (File[M]) Collection ¶
func (File[M]) EmailAttachment ¶
func (f File[M]) EmailAttachment() (email.Attachment, error)
EmailAttachment snapshots this ready file into email's durable reference. No bytes are read. Authorize the file before use and retain its object for queued delivery. The mailer must have access to the same configured disk. Attachment promotes this method from its embedded File.
func (File[M]) Info ¶
func (f File[M]) Info() UploadInfo
func (File[M]) MarshalJSON ¶
func (File[M]) Properties ¶
func (f File[M]) Properties() (json.RawMessage, error)
func (File[M]) Variant ¶
func (f File[M]) Variant(variant Variant) (VariantInfo, bool)
Variant reports whether the declared variant has been generated.
func (File[M]) Variants ¶
func (f File[M]) Variants() []VariantInfo
Variants returns the attachment's generated variants, ordered by name.
type FileSource ¶
FileSource is an upload the framework can open and read, such as foundryhttp.UploadedFile, which satisfies it without attachments importing HTTP. An operation opens it, reads within the policy's MaxBytes and closes its reader before returning; the caller keeps owning the underlying file. Detected bytes decide acceptance: Name is display metadata and ClientContentType only the existing text-specialization hint.
type Hook ¶
type Hook[M any, K comparable] struct { Before func(context.Context, BeforeContext[M, K]) error AfterStored func(context.Context, *database.Tx, Attachment[M, K]) error }
Hooks execute in declaration order. AfterStored runs inside the ownership transaction after storage succeeds and can veto publication. External effects from that hook must use an ordinary transactional outbox or after-commit hook.
type LocalizedBatch ¶
type LocalizedBatch[M any, K comparable] struct { // contains filtered or unexported fields }
LocalizedBatch captures one catalog and owner/attachment snapshot. Resolving many owners or changing the requested locale performs no further I/O.
func (LocalizedBatch[M, K]) Get ¶
func (b LocalizedBatch[M, K]) Get(owner model.Reference[M, K]) (LocalizedFiles[M, K], error)
type LocalizedFiles ¶
type LocalizedFiles[M any, K comparable] struct { // contains filtered or unexported fields }
func (LocalizedFiles[M, K]) List ¶
func (f LocalizedFiles[M, K]) List(locale i18n.LocaleID) ([]Attachment[M, K], error)
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
func New ¶
func New(dependencies Dependencies, config Config, collections ...Registration) (*Manager, error)
func (*Manager) Close ¶
Close cancels reads, writes and owner cleanup together and waits for their actual exit. A timed-out wait keeps ownership visible through Done.
func (*Manager) GenerateVariants ¶
func (m *Manager) GenerateVariants(ctx context.Context, id OperationID) error
GenerateVariants derives every declared variant still missing for one ready attachment. It is idempotent and is the handler of the variant job; an original that is no longer ready has nothing to generate.
func (*Manager) Inspect ¶
func (m *Manager) Inspect(ctx context.Context, id OperationID) (ReconcileResult, error)
Inspect is an administrative, read-only lookup of a durable upload operation. Ready confirms publication; cleanup/cleaned confirms retirement. A writing or uncertain state cannot establish that a remote storage request has settled.
func (*Manager) InspectOrphans ¶
func (m *Manager) InspectOrphans(ctx context.Context, owner extensions.OwnerName, cursor Cursor, limit int) (OrphanPage, error)
func (*Manager) InspectStorage ¶
func (m *Manager) InspectStorage(ctx context.Context, options StorageInspection) (StorageOrphanPage, error)
InspectStorage lists one bounded page under this owner's exact framework prefix on a registered collection disk, then checks those keys in one query. Every journal state protects its object, including unsettled writes. Untracked candidates are inspection results only: their age never authorizes deletion.
func (*Manager) PruneOrphans ¶
func (m *Manager) PruneOrphans(ctx context.Context, owner extensions.OwnerName, ids []OperationID, queue *Queue) (ChangeResult, error)
PruneOrphans only retires ready/stored orphan rows selected explicitly. It preserves soft-deleted owners, and refuses unsettled writers instead of treating owner absence as permission to delete a possibly in-flight upload.
func (*Manager) Reconcile ¶
func (m *Manager) Reconcile(ctx context.Context, id OperationID) (ReconcileResult, error)
func (*Manager) ReconcilePending ¶
ReconcilePending is an explicit bounded sweep, suitable for an ordinary scheduled job. It retries Cleanup and abandons old Stored intents after the configured grace. Writing/Uncertain intents older than the settlement cutoff are inspected with Stat and settled only when storage is unambiguous: absent, or present with this intent's exact size and full checksum. Anything else stays Uncertain for operator Settle. Locally active writers are excluded. The same sweep retries variant cleanup and settles aged variant intents.
func (*Manager) RegenerateVariants ¶
func (m *Manager) RegenerateVariants(ctx context.Context, owner extensions.OwnerName, collection Name, options RegenerationOptions) (RegenerationPage, error)
RegenerateVariants is the name-addressed form used by operational commands.
func (*Manager) RetainedObject ¶
func (m *Manager) RetainedObject(ctx context.Context, id OperationID) (RetainedFile, error)
RetainedObject is an administrative recovery lookup after an uncertain DetachKeepFile commit. It grants no access to ready or unsettled upload pins.
func (*Manager) Settle ¶
func (m *Manager) Settle(ctx context.Context, id OperationID, settlement Settlement, queue *Queue) (ReconcileResult, error)
Settle abandons an unresolved upload after an explicit operator assertion. It never publishes attachment ownership. A matching object is read through a pinned validator and checksum-verified before being scheduled for cleanup.
type Many ¶
type Many[M any] struct { // contains filtered or unexported fields }
Many is a model slot holding the ready files of a multiple-file collection in collection order. The zero value is not loaded.
func (Many[M]) MarshalJSON ¶
type ManyHandle ¶
type ManyHandle[M any, K comparable] struct { // contains filtered or unexported fields }
ManyHandle retains typed slot capabilities behind shared callback state. Example: slot.From(manager).Relation(Fields.Slot).
func ManyOf ¶
func ManyOf[M any, K comparable](owner extensions.Owner[M, K], name Name, policy Policy, binding extensions.SlotBinding[M, K, Many[M]]) ManyHandle[M, K]
ManyOf declares a thin multiple-file handle with the existing manager policy. Example: attachments.ManyOf(owner,"files",policy,binding).
func (ManyHandle[M, K]) Accepts ¶
func (s ManyHandle[M, K]) Accepts(ctx context.Context, file FileSource) (bool, error)
Accepts checks policy using the existing manager admission and media checks. Example: slot.Accepts(ctx,file).
func (ManyHandle[M, K]) Add ¶
Add appends an upload to the multiple-file collection. Example: slot.Add(ctx,article,upload).
func (ManyHandle[M, K]) AddFile ¶
func (s ManyHandle[M, K]) AddFile(ctx context.Context, owner M, file FileSource) (Result[M, K], error)
AddFile appends a file to the multiple-file collection. Example: slot.AddFile(ctx,article,file).
func (ManyHandle[M, K]) AddIn ¶
func (s ManyHandle[M, K]) AddIn(ctx context.Context, tx *database.Tx, owner M, prepared Prepared[M, K]) (Result[M, K], error)
AddIn publishes a prepared upload in the caller transaction. Example: slot.AddIn(ctx,tx,article,prepared).
func (ManyHandle[M, K]) Clear ¶
func (s ManyHandle[M, K]) Clear(ctx context.Context, owner M) (ChangeResult, error)
Clear retires every file and schedules storage cleanup. Example: slot.Clear(ctx,article).
func (ManyHandle[M, K]) Describe ¶
func (s ManyHandle[M, K]) Describe() extensions.SlotDescription
Describe returns an owned inspection snapshot. Example: slot.Describe().
func (ManyHandle[M, K]) Detach ¶
func (s ManyHandle[M, K]) Detach(ctx context.Context, owner M, id ID[M]) (ChangeResult, error)
Detach retires one file and schedules storage cleanup. Example: slot.Detach(ctx,article,id).
func (ManyHandle[M, K]) Discard ¶
func (s ManyHandle[M, K]) Discard(ctx context.Context, prepared Prepared[M, K]) error
Discard reclaims an unpublished prepared upload. Example: slot.Discard(ctx,prepared).
func (ManyHandle[M, K]) Format ¶
func (ManyHandle[M, K]) Format(s fmt.State, _ rune)
Format omits retained runtime state. Example: fmt.Sprintf("%+v",slot).
func (ManyHandle[M, K]) From ¶
func (s ManyHandle[M, K]) From(m *Manager) ManyHandle[M, K]
From returns a copy borrowing this family's manager; nil leaves it unbound. Example: slot.From(manager).
func (ManyHandle[M, K]) Name ¶
func (s ManyHandle[M, K]) Name() Name
Name returns the stored name. Example: slot.Name().
func (ManyHandle[M, K]) Prepare ¶
func (s ManyHandle[M, K]) Prepare(ctx context.Context, owner M, upload Upload) (Prepared[M, K], error)
Prepare prepares storage before a transaction without publishing it. Example: slot.Prepare(ctx,article,upload).
func (ManyHandle[M, K]) PrepareFile ¶
func (s ManyHandle[M, K]) PrepareFile(ctx context.Context, owner M, file FileSource) (Prepared[M, K], error)
PrepareFile prepares file storage before a transaction without publishing it. Example: slot.PrepareFile(ctx,article,file).
func (ManyHandle[M, K]) PublicURLs ¶
func (s ManyHandle[M, K]) PublicURLs(ctx context.Context, owner M) ([]string, error)
PublicURLs derives loaded file URLs in collection order without I/O. Example: slot.PublicURLs(ctx,article).
func (ManyHandle[M, K]) Registration ¶
func (s ManyHandle[M, K]) Registration() Registration
Registration returns the existing manager registration. Example: slot.Registration().
func (ManyHandle[M, K]) Relation ¶
func (s ManyHandle[M, K]) Relation(slot orm.Slot[M, Many[M]]) orm.ExtensionRelation[M]
Relation binds the loader to its concrete ORM field; mismatched fields fail validation. Example: Articles.Query().With(slot.Relation(Articles.Gallery)).
func (ManyHandle[M, K]) Reorder ¶
func (s ManyHandle[M, K]) Reorder(ctx context.Context, owner M, order []ID[M]) ([]Attachment[M, K], error)
Reorder sets an exact permutation of the collection file IDs. Example: slot.Reorder(ctx,article,order).
func (ManyHandle[M, K]) Replace ¶
func (s ManyHandle[M, K]) Replace(ctx context.Context, owner M, upload Upload) (Result[M, K], error)
Replace replaces the collection; inspect the publication outcome when an error is returned. Example: slot.Replace(ctx,article,upload).
func (ManyHandle[M, K]) ReplaceFile ¶
func (s ManyHandle[M, K]) ReplaceFile(ctx context.Context, owner M, file FileSource) (Result[M, K], error)
ReplaceFile replaces the collection from a file; inspect the publication outcome on error. Example: slot.ReplaceFile(ctx,article,file).
func (ManyHandle[M, K]) ReplaceIn ¶
func (s ManyHandle[M, K]) ReplaceIn(ctx context.Context, tx *database.Tx, owner M, prepared Prepared[M, K]) (Result[M, K], error)
ReplaceIn publishes a prepared upload in the caller transaction. Example: slot.ReplaceIn(ctx,tx,article,prepared).
func (ManyHandle[M, K]) TemporaryURL ¶
func (s ManyHandle[M, K]) TemporaryURL(ctx context.Context, owner M, file File[M], options storage.LinkOptions) (storage.TemporaryURL, error)
TemporaryURL signs a loaded file URL pinned to its stored version. Example: slot.TemporaryURL(ctx,article,file,options).
func (ManyHandle[M, K]) URL ¶
URL derives a loaded file URL without I/O; authorize access first. Example: slot.URL(ctx,article,file).
func (ManyHandle[M, K]) Validate ¶
func (s ManyHandle[M, K]) Validate() error
Validate checks the declaration and slot binding. Example: slot.Validate().
func (ManyHandle[M, K]) VariantURL ¶
func (s ManyHandle[M, K]) VariantURL(ctx context.Context, owner M, file File[M], variant Variant) (string, error)
VariantURL derives a generated variant URL without I/O. Example: slot.VariantURL(ctx,article,file,variant).
type One ¶
type One[M any] struct { // contains filtered or unexported fields }
One is a model slot holding the ready file of a single-file collection. The zero value is not loaded. Reading a slot performs no I/O.
func (One[M]) EmailAttachment ¶
func (o One[M]) EmailAttachment() (email.Attachment, error)
EmailAttachment accepts a loaded, present single-file slot directly through Message.AttachStored. An unloaded or absent slot is an error.
func (One[M]) Get ¶
Get returns the optional file and whether the slot was loaded. A loaded but absent file differs from a slot that was not loaded.
func (One[M]) MarshalJSON ¶
type OneHandle ¶
type OneHandle[M any, K comparable] struct { // contains filtered or unexported fields }
OneHandle retains typed slot capabilities behind shared callback state. Example: slot.From(manager).Relation(Fields.Slot).
func OneOf ¶
func OneOf[M any, K comparable](owner extensions.Owner[M, K], name Name, policy Policy, binding extensions.SlotBinding[M, K, One[M]]) OneHandle[M, K]
OneOf declares a thin single-file handle with the existing manager policy. Example: attachments.OneOf(owner,"files",policy,binding).
func (OneHandle[M, K]) Accepts ¶
Accepts checks policy using the existing manager admission and media checks. Example: slot.Accepts(ctx,file).
func (OneHandle[M, K]) Clear ¶
func (s OneHandle[M, K]) Clear(ctx context.Context, owner M) (ChangeResult, error)
Clear retires every file and schedules storage cleanup. Example: slot.Clear(ctx,article).
func (OneHandle[M, K]) Describe ¶
func (s OneHandle[M, K]) Describe() extensions.SlotDescription
Describe returns an owned inspection snapshot. Example: slot.Describe().
func (OneHandle[M, K]) Detach ¶
Detach retires one file and schedules storage cleanup. Example: slot.Detach(ctx,article,id).
func (OneHandle[M, K]) Discard ¶
Discard reclaims an unpublished prepared upload. Example: slot.Discard(ctx,prepared).
func (OneHandle[M, K]) Format ¶
Format omits retained runtime state. Example: fmt.Sprintf("%+v",slot).
func (OneHandle[M, K]) From ¶
From returns a copy borrowing this family's manager; nil leaves it unbound. Example: slot.From(manager).
func (OneHandle[M, K]) Prepare ¶
func (s OneHandle[M, K]) Prepare(ctx context.Context, owner M, upload Upload) (Prepared[M, K], error)
Prepare prepares storage before a transaction without publishing it. Example: slot.Prepare(ctx,article,upload).
func (OneHandle[M, K]) PrepareFile ¶
func (s OneHandle[M, K]) PrepareFile(ctx context.Context, owner M, file FileSource) (Prepared[M, K], error)
PrepareFile prepares file storage before a transaction without publishing it. Example: slot.PrepareFile(ctx,article,file).
func (OneHandle[M, K]) PublicURL ¶
PublicURL derives the loaded single file URL without I/O. Example: slot.PublicURL(ctx,article).
func (OneHandle[M, K]) Registration ¶
func (s OneHandle[M, K]) Registration() Registration
Registration returns the existing manager registration. Example: slot.Registration().
func (OneHandle[M, K]) Relation ¶
Relation binds the loader to its concrete ORM field; mismatched fields fail validation. Example: Articles.Query().With(slot.Relation(Articles.Cover)).
func (OneHandle[M, K]) Replace ¶
Replace replaces the collection; inspect the publication outcome when an error is returned. Example: slot.Replace(ctx,article,upload).
func (OneHandle[M, K]) ReplaceFile ¶
func (s OneHandle[M, K]) ReplaceFile(ctx context.Context, owner M, file FileSource) (Result[M, K], error)
ReplaceFile replaces the collection from a file; inspect the publication outcome on error. Example: slot.ReplaceFile(ctx,article,file).
func (OneHandle[M, K]) ReplaceIn ¶
func (s OneHandle[M, K]) ReplaceIn(ctx context.Context, tx *database.Tx, owner M, prepared Prepared[M, K]) (Result[M, K], error)
ReplaceIn publishes a prepared upload in the caller transaction. Example: slot.ReplaceIn(ctx,tx,article,prepared).
func (OneHandle[M, K]) TemporaryURL ¶
func (s OneHandle[M, K]) TemporaryURL(ctx context.Context, owner M, file File[M], options storage.LinkOptions) (storage.TemporaryURL, error)
TemporaryURL signs a loaded file URL pinned to its stored version. Example: slot.TemporaryURL(ctx,article,file,options).
func (OneHandle[M, K]) URL ¶
URL derives a loaded file URL without I/O; authorize access first. Example: slot.URL(ctx,article,file).
type Operation ¶
type Operation struct{}
OperationID is the administrative/job reference for one durable upload intent. Application collection operations use model-owned ID[M] instead.
type OperationID ¶
type Orphan ¶
type Orphan struct {
Operation OperationID `json:"operation"`
Collection Name `json:"collection"`
Locale i18n.LocaleID `json:"locale"`
State State `json:"state"`
}
type OrphanPage ¶
type Policy ¶
type Policy struct {
Disk storage.Declaration
Cardinality Cardinality
Localized bool
MaxFiles int
MaxBytes int64
MaxStoredBytes int64
Accepted []storage.MediaType
AnyMedia bool
Image value.Optional[imaging.Plan]
// Variants are named derived images (for example thumbnails) generated
// from each ready original and stored beside it. They require image input:
// an Image plan or an Accepted list of decodable image types.
Variants []Variant
// InlineActiveContent allows public URLs and inline signed links for
// script-capable files (SVG, HTML, XML, JavaScript). By default public URLs
// are refused and signed links force a download disposition, because such
// files served inline run scripts in the serving origin (stored XSS). Only
// set it when that origin is isolated and cookie-less.
InlineActiveContent bool
}
type Prepared ¶
type Prepared[M any, K comparable] struct { // contains filtered or unexported fields }
Prepared is an upload read, checked and stored for one owner's collection but not yet published. Publish it with ReplaceIn or AddIn inside a transaction that begins after Prepare returned, within StoredGrace; otherwise ReconcilePending reclaims it. Discard reclaims it at once.
func (Prepared[M, K]) Operation ¶
func (p Prepared[M, K]) Operation() OperationID
Operation is the durable upload intent, for Manager.Inspect.
type Publication ¶
type Publication uint8
const ( Unpublished Publication = iota Published PublicationUnknown )
type Queue ¶
type Queue struct {
// contains filtered or unexported fields
}
Queue is a borrowed job/outbox binding. Construct the manager, declare its reconcile job, assemble the ordinary dispatcher/outbox, then bind the queue to collections. This avoids constructor dependency cycles.
type ReconcileJob ¶
type ReconcileJob struct {
// contains filtered or unexported fields
}
func DefineReconcileJob ¶
func DefineReconcileJob(name jobs.Name, policy jobs.Policy) ReconcileJob
func (ReconcileJob) Declare ¶
func (j ReconcileJob) Declare(manager *Manager) (jobs.Declaration, error)
type ReconcileRequest ¶
type ReconcileRequest struct {
Operation OperationID `json:"operation"`
}
type ReconcileResult ¶
type ReconcileResult struct {
Operation OperationID
State State
Attempts uint32
Failure string
}
type RegenerationCursor ¶
type RegenerationCursor struct {
// contains filtered or unexported fields
}
RegenerationCursor continues a regeneration run within one process.
func (RegenerationCursor) IsZero ¶
func (c RegenerationCursor) IsZero() bool
type RegenerationOptions ¶
type RegenerationOptions struct {
Missing bool
Cursor RegenerationCursor
Limit int
}
RegenerationOptions selects one bounded batch of ready attachments. Missing generates only variants without a ready file; otherwise every declared variant is regenerated and replaces the previous one.
type RegenerationPage ¶
type RegenerationPage struct {
Regenerated []OperationID
Failed []OperationID
Next RegenerationCursor
}
RegenerationPage reports one batch. Failed attachments keep their previous variants; rerun them after resolving the cause. Continue with Next until it is zero.
type Registration ¶
type Registration struct {
// contains filtered or unexported fields
}
type RemoteSource ¶
type RemoteSource struct {
Client *httpclient.Client
URL string
OriginalName string
}
RemoteSource names a remote file to import. URL is untrusted input, so Client must enforce a restricted destination policy (for example httpclient.PublicDestinations) that keeps imports away from internal services. OriginalName defaults to the URL's last path segment.
type Resolved ¶
type Resolved[M any, K comparable] struct { // contains filtered or unexported fields }
func (Resolved[M, K]) Files ¶
func (r Resolved[M, K]) Files() []Attachment[M, K]
type Result ¶
type Result[M any, K comparable] struct { Operation OperationID Publication Publication Attachment value.Optional[Attachment[M, K]] PendingCleanup []OperationID PendingVariants bool }
Result distinguishes ownership publication from storage cleanup. A published attachment remains published when old-object cleanup returns an error. An uncertain publication is never described as rolled back or automatically retried. Inspect the durable Operation before deciding the next action. PendingVariants reports that declared variants were queued, or that their synchronous generation failed; the original is published either way.
func AddFilesTo ¶
func AddFilesTo[F FileSource, M any, K comparable](ctx context.Context, slot ManyHandle[M, K], owner M, files []F) ([]Result[M, K], error)
AddFilesTo appends files through a bound ORM many-slot handle in input order. The slot and batch limit are checked before any file opens. Results include every attempted file, including the first failure; earlier publications remain published. Inspect each Result.Publication and never retry unknown outcomes. Example: results, err := attachments.AddFilesTo(ctx, bound.Galleries, article, files).
func (Result[M, K]) MarshalJSON ¶
type RetainResult ¶
type RetainResult struct {
Operation OperationID
Publication Publication
File value.Optional[RetainedFile]
}
type RetainedFile ¶
type RetainedFile struct {
Operation OperationID
Disk storage.DiskID
Key storage.ObjectKey
ETag storage.ETag
Version storage.VersionID
}
RetainedFile transfers cleanup responsibility to the application. Its exact storage pins are explicit; automatic attachment maintenance never deletes it.
func (RetainedFile) MarshalJSON ¶
func (RetainedFile) MarshalJSON() ([]byte, error)
type Settlement ¶
type Settlement uint8
Settlement is an operator assertion, after inspecting the writer and storage provider, that no request can still publish this upload. It is never inferred from a lease, canceled context or one missing-object response; the automatic path relies instead on the configured writer/provider time bound.
const WriterStoppedAndStorageSettled Settlement = 1
type State ¶
type State string
State is persisted, public diagnostic state, not a caller-controlled upload option. Writing/Uncertain require settlement; a timeout alone is not proof that a remote storage request has stopped. ReconcilePending settles them only after the disk Timeout plus Config.SettleAfter and only when storage is unambiguous; everything else waits for an operator Settle.
type StorageCursor ¶
type StorageCursor struct {
// contains filtered or unexported fields
}
StorageCursor preserves the disk/owner/age policy and first-page cutoff. Listings are not transactional snapshots. Copy only a returned Next cursor.
func (StorageCursor) IsZero ¶
func (c StorageCursor) IsZero() bool
type StorageInspection ¶
type StorageInspection struct {
Disk storage.Declaration
Owner extensions.OwnerName
MinimumAge time.Duration
Limit int
Cursor StorageCursor
}
type StorageOrphanPage ¶
type StorageOrphanPage struct {
Candidates []storage.ObjectInfo
Scanned int
Next StorageCursor
}
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 collection names in owner's current scope that no collection registered with m declares, in any journal state, for example after renaming a slot field without pinning its stored name. It reads names only and modifies no row or object.
type Upload ¶
type Upload struct {
Source io.Reader
OriginalName string
ContentType storage.MediaType
Properties value.JSON[json.RawMessage]
}
Upload borrows Source until the operation actually returns and never closes it. OriginalName and ContentType are untrusted metadata hints. Media acceptance is based on bytes; ContentType can only specialize generic plain text to a compatible textual type (CSV, TSV, Markdown, calendar, valid JSON) that the policy accepts, otherwise the file stays text/plain. Image policy performs actual bounded decode/re-encoding. Invisible bidirectional and zero-width characters are removed from OriginalName.
type UploadInfo ¶
type Variant ¶
type Variant struct {
// contains filtered or unexported fields
}
Variant declares a named derived image, for example a thumbnail or preview. It is generated from each ready original with an imaging plan and stored beside it; the original is never changed. Declare it once and reuse the same value in collection policies and link helpers.
func DefineVariant ¶
func DefineVariant(name VariantName, plan imaging.Plan) Variant
func (Variant) Name ¶
func (v Variant) Name() VariantName
type VariantInfo ¶
type VariantInfo struct {
Name VariantName
MediaType storage.MediaType
Size int64
Width, Height int
}
VariantInfo describes one generated variant of a loaded attachment.
type VariantJob ¶
type VariantJob struct {
// contains filtered or unexported fields
}
VariantJob generates missing variants of one ready attachment. Retries are idempotent: completed variants are not generated again.
func DefineVariantJob ¶
func DefineVariantJob(name jobs.Name, policy jobs.Policy) VariantJob
func (VariantJob) Declare ¶
func (j VariantJob) Declare(manager *Manager) (jobs.Declaration, error)
func (VariantJob) ToOutbox ¶
func (j VariantJob) ToOutbox(producer *jobs.Outbox) (VariantQueue, error)
type VariantName ¶
type VariantName string
VariantName is a stable semantic identifier stored with each derived file.
func (VariantName) Validate ¶
func (n VariantName) Validate() error
type VariantQueue ¶
type VariantQueue struct {
// contains filtered or unexported fields
}
VariantQueue is a borrowed job/outbox binding for queued variant generation. Bind it with Collection.WithVariantQueue after the manager and its job are declared; the publication transaction then enqueues one job per upload.
func (VariantQueue) Validate ¶
func (q VariantQueue) Validate() error
type VariantRequest ¶
type VariantRequest struct {
Operation OperationID `json:"operation"`
}
VariantRequest identifies one attachment whose declared variants are generated.
type VariantState ¶
type VariantState string
VariantState is the persisted journal state of one derived file.
const ( VariantWriting VariantState = "writing" VariantReady VariantState = "ready" VariantCleanup VariantState = "cleanup" VariantCleaned VariantState = "cleaned" VariantUncertain VariantState = "uncertain" )
func (VariantState) Validate ¶
func (s VariantState) Validate() error
Source Files
¶
- definition.go
- diagnostics.go
- email.go
- handle_collection.go
- handle_core.go
- handle_files.go
- handle_many.go
- handle_one.go
- inspection.go
- jobs.go
- lifecycle.go
- localized.go
- manager.go
- matching.go
- migrations.go
- module.go
- mutate.go
- orphans.go
- read.go
- reconcile.go
- remote.go
- result.go
- retain.go
- row.go
- scopes.go
- slot.go
- slot_write.go
- state.go
- storage_diagnostics.go
- storage_outcome.go
- upload.go
- variants.go
- write.go