Help us shape the future of Go! Take the 2026 Go Developer Survey

store

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package store defines artifactweave's metadata persistence contracts (decision 0004) over the domain types of pkg/types and pkg/repo.

Design

Store composes one interface per concern so services and fakes depend only on what they use. Every method takes a context. Tx runs a function whose context makes every store call inside it part of one transaction; that is how a deploy writes the item, its properties, the blob reference and the outbox entry for federation together, or not at all (decision 0021). Returned values are copies: mutating one never changes stored state.

Records are keyed by their wire identities (repository key, user name, token id, the (name, version) of a release bundle). Records without one (items, runs, executions, deliveries) get an int64 identifier from the store, increasing in creation order.

Lists are keyset-paginated. A Page carries an opaque cursor from the previous call's next value; a list returns next == "" on its last page. Each list documents its order, which is stable under concurrent inserts.

Times are stored in UTC at microsecond precision and durations at millisecond precision, which is what the SQL columns hold; a zero time means "not set" and comes back zero. Every backend normalises on write, so a value read back equals the value written once normalised.

Sealed fields (decision 0017) are given and returned in plain text; the SQL stores seal them with the configured keyring and keep them out of every JSON document column, so no listing or document read can leak one.

pkg/store/inmem is the reference implementation, internal/sqlstore implements the same contract for SQLite and PostgreSQL, and storetest is the contract suite every backend runs.

References

  • Decision 0004: docs/research/decisions/0004-storage-sql-metadata-and-blobs.md
  • Decision 0017: docs/research/decisions/0017-sealed-columns-and-master-key.md
  • Research 15 section 4: docs/research/15-data-model.md

Index

Constants

View Source
const (
	DefaultLimit = 100
	MaxLimit     = 1000
)

Page bounds.

View Source
const (
	MaxWorkKind    = 64
	MaxWorkKey     = 1024
	MaxWorkPayload = 64 << 10
)

Bounds on a work item, so the queue stays a queue of references to work rather than a store of its data (decision 0033).

Variables

View Source
var (
	// ErrNotFound reports that a keyed record does not exist.
	ErrNotFound = errors.New("store: not found")
	// ErrConflict reports a create that collides with an existing key, or a
	// change that would break a uniqueness rule.
	ErrConflict = errors.New("store: conflict")
	// ErrDeleting reports a blob whose content garbage collection is
	// removing: it cannot be referenced until the removal has finished.
	ErrDeleting = errors.New("store: blob is being deleted")
	// ErrInvalidCursor reports a malformed pagination cursor.
	ErrInvalidCursor = errors.New("store: invalid cursor")
	// ErrInvalid reports a record the store cannot hold as given, for
	// example an item path that does not split into parent and name.
	ErrInvalid = errors.New("store: invalid record")
)

Sentinel errors. Implementations wrap them; callers test with errors.Is.

Functions

func AQLSource

func AQLSource(s Store) aql.Source

AQLSource is s as the source of the rows an AQL include of related domains reaches (aql.Query.Nest): runs by the checksum of their files, files by checksum, runs by ID and their promotions. It reads through the store's own lookups, so every backend nests the same rows.

func CheckBuildPropertyKeys

func CheckBuildPropertyKeys(b types.Build) error

CheckBuildPropertyKeys is CheckPropertyKeys over b's build and module properties.

func CheckPropertyKeys

func CheckPropertyKeys(props types.Properties) error

CheckPropertyKeys returns ErrInvalid, wrapping types.ErrPropertyKeyTooLong, when a key of props is longer than types.PropertyKeyMax. Every store checks before it writes, so a property write either stores every key or none, whichever route it came by.

func CleanProperties

func CleanProperties(props types.Properties, limit int) types.Properties

CleanProperties is how the stores keep properties, one row per value: keys without values dropped, each value cut to limit (types.TruncatePropertyValue), and the values sorted and unique, so two values that differ only past the limit become one.

func Clone

func Clone[V any](v V) V

Clone deep-copies v: maps, slices and pointers are duplicated, nil stays nil and empty stays empty, so a caller can neither see nor make later changes to stored state.

func Cursor

func Cursor(parts ...string) string

Cursor returns the opaque cursor that continues a list after the record whose sort key is parts. Implementations call it for the last record of a page; callers treat the result as opaque.

func Normalise

func Normalise[V any](v V) V

Normalise is Clone with times truncated to UTC microseconds and durations to milliseconds, the precision of the SQL columns: what every backend returns for a value it was given. Contract tests build their expectations with it.

func NormaliseBuild

func NormaliseBuild(b types.Build) types.Build

NormaliseBuild is what every backend stores and returns for b: Normalise, with build and module properties cleaned (CleanProperties) to types.BuildPropertyValueMax.

func Trim

func Trim[T any](rows []T, limit int, key func(T) []string) ([]T, string)

Trim cuts rows, fetched with one more row than limit, to the page and returns the cursor of the next page ("" when rows was the last page). key returns a record's sort key, the parts Page.Key decodes.

func ValidateLease

func ValidateLease(req WorkLease) error

ValidateLease checks a lease request.

func ValidateWork

func ValidateWork(kind, key string, payload []byte) error

ValidateWork checks an item to enqueue against the queue's bounds.

Types

type ArchiveStore

type ArchiveStore interface {
	// CreatePolicy stores p; ErrConflict when the key exists.
	CreatePolicy(ctx context.Context, p types.ArchivePolicy) error
	// Policy returns the policy.
	Policy(ctx context.Context, key string) (types.ArchivePolicy, error)
	// UpdatePolicy replaces the policy.
	UpdatePolicy(ctx context.Context, p types.ArchivePolicy) error
	// DeletePolicy removes the policy; its executions and items are kept.
	DeletePolicy(ctx context.Context, key string) error
	// Policies returns a family's policies ("" for both) ordered by key.
	Policies(ctx context.Context, family types.ArchiveFamily) ([]types.ArchivePolicy, error)

	// CreateExecution stores e and returns it with its assigned ID.
	CreateExecution(ctx context.Context, e types.ArchiveExecution) (types.ArchiveExecution, error)
	// Execution returns the execution with id.
	Execution(ctx context.Context, id int64) (types.ArchiveExecution, error)
	// UpdateExecution replaces an execution.
	UpdateExecution(ctx context.Context, e types.ArchiveExecution) error
	// Executions returns matching executions newest first.
	Executions(
		ctx context.Context,
		f ExecutionFilter,
		p Page,
	) ([]types.ArchiveExecution, string, error)

	// AddItem stores an archived item and returns it with its assigned ID;
	// ErrInvalid when the item's full path does not split
	// (types.SplitItemPath).
	AddItem(ctx context.Context, a types.ArchivedItem) (types.ArchivedItem, error)
	// Item returns the archived item with id.
	Item(ctx context.Context, id int64) (types.ArchivedItem, error)
	// FindItems returns the archived copies of an original repository and
	// full path, newest first by ID; ErrInvalid for a path that does not
	// split.
	FindItems(ctx context.Context, repoKey, fullPath string) ([]types.ArchivedItem, error)
	// Items returns matching archived items ordered by ID; a zero
	// ExecutionID matches every execution.
	Items(ctx context.Context, f ArchivedFilter, p Page) ([]types.ArchivedItem, string, error)
	// DeleteItem removes an archived item.
	DeleteItem(ctx context.Context, id int64) error
	// ExpiredItems returns items whose ExpiresAt is set and before t,
	// oldest first, at most limit (DefaultLimit when zero).
	ExpiredItems(ctx context.Context, before time.Time, limit int) ([]types.ArchivedItem, error)

	// ColdBlobs is the cold tier's blob index.
	ColdBlobs() BlobIndex
	// ColdReplicas is the cold tier's replica index, for a mirrored cold
	// tier.
	ColdReplicas() ReplicaIndex
}

ArchiveStore persists the cold-storage tier's records (decision 0024): archive policies of both families, executions, archived items and the cold blob index.

type ArchivedFilter

type ArchivedFilter struct {
	RepoKey     string
	PolicyKey   string
	ExecutionID int64
}

ArchivedFilter narrows archived item listings.

type BlobIndex

type BlobIndex interface {
	// Ref adds n references to b and returns the row as updated. An absent
	// row is created live; a tombstone is revived, keeping Deleted.
	// ErrDeleting while the row is deleting; ErrConflict when the stored size
	// or checksums differ from b's, which means two different contents claim
	// one sha256.
	Ref(ctx context.Context, b types.Blob, n int64) (types.Blob, error)
	// Unref removes n references, never going below zero, and returns the
	// row as updated.
	Unref(ctx context.Context, sha256 string, n int64) (types.Blob, error)
	// Get returns the row for sha256, in whatever state.
	Get(ctx context.Context, sha256 string) (types.Blob, error)
	// Find returns the live blob matching the strongest digest set in c
	// (sha256, then sha1, then md5). SHA512 is not a lookup key, as for
	// FindByChecksum.
	Find(ctx context.Context, c types.Checksums) (types.Blob, error)
	// Unreferenced lists live blobs with no references, ordered by sha256.
	Unreferenced(ctx context.Context, p Page) ([]types.Blob, string, error)
	// MarkDeleting starts removing b's content: an unreferenced live row or a
	// tombstone becomes deleting at at, and content the index has no row for
	// gets a deleting row from b. A row already deleting is returned as it
	// is. ErrConflict while the row is referenced.
	MarkDeleting(ctx context.Context, b types.Blob, at time.Time) (types.Blob, error)
	// FinishDelete turns a deleting row into a tombstone deleted at at, once
	// its content is gone. A tombstone is left as it is; ErrConflict for a
	// live row, ErrNotFound when there is no row.
	FinishDelete(ctx context.Context, sha256 string, at time.Time) error
	// Deleting lists the rows being deleted, ordered by sha256, so a pass
	// can finish what a crashed one started.
	Deleting(ctx context.Context, p Page) ([]types.Blob, string, error)
	// Prune drops tombstones deleted before before and clears Deleted on
	// live rows deleted before then, returning how many rows changed.
	Prune(ctx context.Context, before time.Time) (int64, error)
	// Totals returns the number of live blobs and their combined size.
	Totals(ctx context.Context) (count, bytes int64, err error)
}

BlobIndex is the content-addressed blob index (the blobs table, and the cold_blobs table for the archive tier). Rows are keyed by sha256 and reference-counted; garbage collection deletes blobs whose count reached zero.

Garbage collection removes a blob in three steps (decision 0010): MarkDeleting, then the content delete, then FinishDelete. A deleting row refuses references, and the tombstone FinishDelete leaves records when the content went, so a deploy that wrote the same content just before it was removed finds out and never references missing content.

type BuildStore

type BuildStore interface {
	// Put stores a new run with its modules and returns it with its
	// assigned ID. ErrConflict when (project, name, number, started)
	// exists; ErrInvalid when the name or number is empty or started is
	// zero.
	Put(ctx context.Context, b types.Build) (types.Build, error)
	// Replace replaces the content of run b.ID: its URL, modification
	// stamp, properties, modules and document. The identity (project,
	// name, number, started) and Created stay as stored. ErrNotFound when
	// the run does not exist.
	Replace(ctx context.Context, b types.Build) error
	// Get returns a run with its modules. A zero started selects the
	// latest-started run of that number. ErrNotFound when there is none.
	Get(
		ctx context.Context,
		projectKey, name, number string,
		started time.Time,
	) (types.Build, error)
	// ByID returns the run with id, with its modules.
	ByID(ctx context.Context, id int64) (types.Build, error)
	// Latest returns the latest-started run of a name, with its modules.
	// ErrNotFound when the name has no runs.
	Latest(ctx context.Context, projectKey, name string) (types.Build, error)
	// Runs lists a name's runs, newest first by (started, ID). A name with
	// no runs lists nothing.
	Runs(ctx context.Context, projectKey, name string, p Page) ([]types.BuildRun, string, error)
	// Names lists a project's build names ordered by name, each with the
	// start of its latest run.
	Names(ctx context.Context, projectKey string, p Page) ([]types.BuildName, string, error)
	// DeleteNumbers deletes one run for each occurrence of a number in
	// numbers, the earliest-started of that number's remaining runs first,
	// and returns the deleted runs in deletion order. An occurrence with no
	// run left is skipped. This is what `jf rt bp --overwrite` expects: it
	// sends a number once per existing run.
	DeleteNumbers(
		ctx context.Context,
		projectKey, name string,
		numbers []string,
	) ([]types.BuildRun, error)
	// DeleteAll deletes every run of a name and its retention, and returns
	// the deleted runs oldest first.
	DeleteAll(ctx context.Context, projectKey, name string) ([]types.BuildRun, error)
	// Rename moves every run of a name, and its retention, to another name.
	// A retention left on to, which has no runs, is replaced by from's or
	// removed when from has none. ErrNotFound when from has no runs;
	// ErrConflict when to has runs. Renaming a name to itself does nothing.
	Rename(ctx context.Context, projectKey, from, to string) error

	// AddPromotion records a promotion of run p.BuildID and returns it
	// with its assigned ID. ErrNotFound when the run does not exist.
	AddPromotion(ctx context.Context, p types.BuildPromotion) (types.BuildPromotion, error)
	// Promotions returns a run's promotions oldest first by (created, ID).
	// ErrNotFound when the run does not exist.
	Promotions(ctx context.Context, buildID int64) ([]types.BuildPromotion, error)

	// FindArtifacts returns the build artifacts whose checksums match every
	// non-empty field of c, across all projects, ordered by run ID, then
	// module and file position. ErrInvalid when c has no checksum.
	FindArtifacts(ctx context.Context, c types.Checksums) ([]types.BuildFileRef, error)
	// FindDependencies is FindArtifacts for dependencies.
	FindDependencies(ctx context.Context, c types.Checksums) ([]types.BuildFileRef, error)

	// Search runs an AQL builds or build.promotions query (decision
	// 0012): the matching runs, or promotions with their runs, in the
	// order aql.SelectBuilds returns them. A hit's run carries its own
	// columns only, not its properties, modules or document. Relation
	// paths reach items by checksum. ErrInvalid for an items query.
	Search(ctx context.Context, q *aql.Query, o aql.Options) ([]aql.BuildHit, error)

	// PutRetention creates or replaces a build name's retention.
	PutRetention(ctx context.Context, r types.BuildRetention) error
	// Retention returns a build name's retention. ErrNotFound when none is
	// set.
	Retention(ctx context.Context, projectKey, name string) (types.BuildRetention, error)
}

BuildStore persists build-info runs (decision 0014): one record per run, keyed by (project, name, number, started), with the document as published and its modules, properties, artifacts and dependencies as rows for the AQL build domains and the checksum searches. A project key of "" is the default project.

The store keeps the document itself and serves reads from it. Writing the copy of the document as an item (types.Build.DocumentItem) belongs to the build service, which holds the blob store: it puts the run and the item in one Tx, so a publish or a delete changes both or neither.

type BundleFilter

type BundleFilter struct {
	Name       string
	Origin     types.BundleOrigin
	ProjectKey string
}

BundleFilter narrows release bundle listings.

type BundleStore

type BundleStore interface {
	// Create stores b with its artifacts, whose BundleName and BundleVersion
	// are set from b; ErrConflict when (name, version) exists or two
	// artifacts share a target path.
	Create(ctx context.Context, b types.ReleaseBundle, artifacts []types.BundleArtifact) error
	// Get returns one bundle version.
	Get(ctx context.Context, name, version string) (types.ReleaseBundle, error)
	// Update replaces the bundle's record; its artifacts are unchanged.
	Update(ctx context.Context, b types.ReleaseBundle) error
	// ReplaceArtifacts replaces the artifact list of an open bundle;
	// ErrConflict once the bundle is signed (types.BundleState.Editable).
	ReplaceArtifacts(
		ctx context.Context,
		name, version string,
		artifacts []types.BundleArtifact,
	) error
	// Delete removes the bundle version with its artifacts, keep mark and
	// export; the audit trail is kept.
	Delete(ctx context.Context, name, version string) error
	// List returns matching bundles ordered by (name, version).
	List(ctx context.Context, f BundleFilter, p Page) ([]types.ReleaseBundle, string, error)
	// Artifacts returns a bundle's artifacts ordered by target path;
	// ErrNotFound when the bundle does not exist.
	Artifacts(ctx context.Context, name, version string) ([]types.BundleArtifact, error)

	// SetKeep marks or unmarks a bundle version as kept from retention;
	// marking twice or unmarking an unmarked version is not an error.
	SetKeep(ctx context.Context, name, version string, keep bool) error
	// Kept reports whether a bundle version is marked kept; ErrNotFound when
	// the bundle does not exist.
	Kept(ctx context.Context, name, version string) (bool, error)
	// AddAudit records a retention operation. The bundle need not exist:
	// the audit outlives the versions retention deletes.
	AddAudit(ctx context.Context, a types.BundleRetentionAudit) error
	// Audits returns a bundle's retention operations ("" for every bundle),
	// newest first by Created.
	Audits(ctx context.Context, name string) ([]types.BundleRetentionAudit, error)

	// PutExport creates or replaces a bundle version's export record;
	// ErrNotFound when the bundle does not exist.
	PutExport(ctx context.Context, e types.BundleExport) error
	// Export returns a bundle version's export record.
	Export(ctx context.Context, name, version string) (types.BundleExport, error)
	// DeleteExport removes it.
	DeleteExport(ctx context.Context, name, version string) error
}

BundleStore persists release bundles v1 (decision 0023) with their frozen artifact lists, retention keep marks and audit, and exports.

type CleanupStore

type CleanupStore interface {
	// CreatePolicy stores p; ErrConflict when the key exists.
	CreatePolicy(ctx context.Context, p types.CleanupPolicy) error
	// Policy returns the policy.
	Policy(ctx context.Context, key string) (types.CleanupPolicy, error)
	// UpdatePolicy replaces the policy.
	UpdatePolicy(ctx context.Context, p types.CleanupPolicy) error
	// DeletePolicy removes the policy; its runs are kept for the run views.
	DeletePolicy(ctx context.Context, key string) error
	// Policies returns matching policies ordered by key.
	Policies(ctx context.Context, f PolicyFilter) ([]types.CleanupPolicy, error)

	// CreateRun stores r and returns it with its assigned ID.
	CreateRun(ctx context.Context, r types.CleanupRun) (types.CleanupRun, error)
	// Run returns the run with id.
	Run(ctx context.Context, id int64) (types.CleanupRun, error)
	// UpdateRun replaces a run.
	UpdateRun(ctx context.Context, r types.CleanupRun) error
	// Runs returns matching runs newest first.
	Runs(ctx context.Context, f RunFilter, p Page) ([]types.CleanupRun, string, error)
	// LastRun returns a policy's most recent run.
	LastRun(ctx context.Context, policyKey string) (types.CleanupRun, error)
}

CleanupStore persists package and build cleanup policies and their runs.

type ConfigStore

type ConfigStore interface {
	// Put creates or replaces the document (d.Kind, d.Key) and its secrets;
	// ErrInvalid when the kind or key is empty.
	Put(ctx context.Context, d types.ConfigDocument) error
	// Get returns one document, secrets included.
	Get(ctx context.Context, kind types.ConfigKind, key string) (types.ConfigDocument, error)
	// List returns the documents of a kind ordered by key.
	List(ctx context.Context, kind types.ConfigKind) ([]types.ConfigDocument, error)
	// Delete removes a document.
	Delete(ctx context.Context, kind types.ConfigKind, key string) error
}

ConfigStore persists configuration documents. Their secrets are sealed; a secret with an empty value is not stored.

type DeleteResult

type DeleteResult struct {
	Files    int64
	Folders  int64
	Bytes    int64
	BlobRefs map[string]int64
}

DeleteResult summarises an ItemStore.Delete. BlobRefs counts, per sha256, the file references removed, which is what the caller passes to BlobIndex.Unref.

type DeliveryFilter

type DeliveryFilter struct {
	WebhookKey string
	From       time.Time
	To         time.Time
	Limit      int
}

DeliveryFilter narrows delivery records to those attempted at or after From and before To. Zero times are open bounds; an empty WebhookKey matches every subscription.

type DigestKind

type DigestKind int

DigestKind selects which token digest ByDigest matches.

const (
	DigestAccess DigestKind = iota + 1
	DigestRefresh
	DigestReference
)

Token digests.

type DistributionStore

type DistributionStore interface {
	// CreateTracker stores t with its jobs and returns it with its assigned
	// ID; the jobs' TrackerID is set to it. ErrConflict when two jobs name
	// the same peer.
	CreateTracker(
		ctx context.Context, t types.DistributionTracker, jobs []types.DistributionJob,
	) (types.DistributionTracker, error)
	// Tracker returns the tracker with id.
	Tracker(ctx context.Context, id int64) (types.DistributionTracker, error)
	// UpdateTracker replaces a tracker.
	UpdateTracker(ctx context.Context, t types.DistributionTracker) error
	// Trackers returns a bundle version's trackers newest first. An empty
	// version selects every version of name, and an empty name every
	// bundle.
	Trackers(ctx context.Context, name, version string) ([]types.DistributionTracker, error)
	// PutJob creates or replaces the job (j.TrackerID, j.PeerInstanceID);
	// ErrNotFound when the tracker does not exist.
	PutJob(ctx context.Context, j types.DistributionJob) error
	// Jobs returns a tracker's jobs ordered by peer; ErrNotFound when the
	// tracker does not exist.
	Jobs(ctx context.Context, trackerID int64) ([]types.DistributionJob, error)
	// JobsForPeer returns a peer's jobs in any of statuses (all when empty),
	// ordered by (tracker, peer).
	JobsForPeer(
		ctx context.Context,
		peer string,
		statuses []types.JobStatus,
	) ([]types.DistributionJob, error)
}

DistributionStore persists distribution trackers and their per-target jobs.

type Download

type Download struct {
	By     string
	At     time.Time
	Remote bool
	Origin string
	Path   string
}

Download is one recorded download of an item. Remote marks a download served to another instance through a smart remote repository, which Artifactory counts separately along with where it went.

type ExecutionFilter

type ExecutionFilter struct {
	PolicyKey string
	Kind      types.ExecutionKind
}

ExecutionFilter narrows archive execution listings.

type FederationStore

type FederationStore interface {
	// SetMembers replaces a repository's members; each member's RepoKey is
	// set to repoKey. ErrInvalid when a member has no PeerInstanceID
	// (members are resolved to peers first), ErrConflict when two name the
	// same peer.
	SetMembers(ctx context.Context, repoKey string, members []types.FederationMember) error
	// Members returns a repository's members ordered by peer.
	Members(ctx context.Context, repoKey string) ([]types.FederationMember, error)
	// MembersWithPeer returns every membership naming peer, ordered by
	// repository.
	MembersWithPeer(ctx context.Context, peer string) ([]types.FederationMember, error)

	// CreateFullSync stores r and returns it with its assigned ID.
	CreateFullSync(ctx context.Context, r types.FullSyncRun) (types.FullSyncRun, error)
	// FullSync returns the run with id.
	FullSync(ctx context.Context, id int64) (types.FullSyncRun, error)
	// UpdateFullSync replaces a run.
	UpdateFullSync(ctx context.Context, r types.FullSyncRun) error
	// FullSyncs returns a repository's runs ("" for all) newest first.
	FullSyncs(ctx context.Context, repoKey string, p Page) ([]types.FullSyncRun, string, error)
}

FederationStore persists federated repository membership (decision 0022) and full-sync runs.

type GroupStore

type GroupStore interface {
	// Create stores g and its members; ErrConflict when the name exists,
	// ErrNotFound when a member does not.
	Create(ctx context.Context, g types.Group) error
	// Get returns the group with Members sorted.
	Get(ctx context.Context, name string) (types.Group, error)
	// Update replaces the group's fields and members.
	Update(ctx context.Context, g types.Group) error
	// Delete removes the group and its memberships.
	Delete(ctx context.Context, name string) error
	// List returns groups ordered by name.
	List(ctx context.Context, p Page) ([]types.Group, string, error)
	// AddMembers adds users to the group; adding a member twice is not an
	// error. ErrNotFound when the group or a user does not exist.
	AddMembers(ctx context.Context, group string, users ...string) error
	// RemoveMembers removes users from the group; removing a non-member is
	// not an error.
	RemoveMembers(ctx context.Context, group string, users ...string) error
	// AutoJoin returns the names of groups new users join, ordered.
	AutoJoin(ctx context.Context) ([]string, error)
}

GroupStore persists groups.

type InstanceStore

type InstanceStore interface {
	// Init stores the identity; ErrConflict when one exists.
	Init(ctx context.Context, id types.InstanceIdentity) error
	// Get returns the identity.
	Get(ctx context.Context) (types.InstanceIdentity, error)
	// Update replaces the identity, for key rotation.
	Update(ctx context.Context, id types.InstanceIdentity) error
}

InstanceStore persists this instance's peer identity (decision 0021), a singleton created at first start. The private key is sealed.

type ItemStore

type ItemStore interface {
	// Put creates the item or replaces the one at the same natural key,
	// keeping that item's ID, and returns it as stored. The store derives
	// Path, Name and Depth from FullPath, so callers may set either Path and
	// Name or a full path in Name; ErrInvalid when it does not split
	// (types.SplitItemPath). Parent folders are not created.
	Put(ctx context.Context, it types.Item) (types.Item, error)
	// Get returns the item at fullPath.
	Get(ctx context.Context, repoKey string, cached bool, fullPath string) (types.Item, error)
	// GetByID returns the item with id.
	GetByID(ctx context.Context, id int64) (types.Item, error)
	// Children lists the items directly inside folder, ordered by name.
	Children(
		ctx context.Context, repoKey string, cached bool, folder string, p Page,
	) ([]types.Item, string, error)
	// Descendants lists every item below folder, ordered by (path, name).
	Descendants(
		ctx context.Context, repoKey string, cached bool, folder string, p Page,
	) ([]types.Item, string, error)
	// Delete removes the item at fullPath and, for a folder, everything
	// below it, with their properties and statistics. A root path removes
	// all of (repoKey, cached) but the root's record, which belongs to the
	// repository rather than its content, and returns a zero result for an
	// empty repository; any other path returns ErrNotFound when nothing is
	// there.
	Delete(ctx context.Context, repoKey string, cached bool, fullPath string) (DeleteResult, error)
	// Root returns the record of the root of (repoKey, cached), ErrNotFound
	// while it has none.
	Root(ctx context.Context, repoKey string, cached bool) (types.Item, error)
	// EnsureRoot returns the record of the root of (r.RepoKey, r.Cached),
	// creating it as types.RootItem with r's times and actors when absent;
	// ErrInvalid without a repository key.
	EnsureRoot(ctx context.Context, r types.Item) (types.Item, error)
	// DeleteRoot removes the record of the root of (repoKey, cached) with
	// its properties, when the repository itself is removed. A root without
	// a record is not an error.
	DeleteRoot(ctx context.Context, repoKey string, cached bool) error
	// FindByChecksum lists files whose actual checksum matches the
	// strongest digest set in c (sha256, then sha1, then md5), ordered by
	// ID. SHA512 is not a lookup key: whatever holds one holds the sha256.
	FindByChecksum(ctx context.Context, c types.Checksums, p Page) ([]types.Item, string, error)
	// Usage returns content totals per repository and cache, ordered by
	// (repository, cached).
	Usage(ctx context.Context) ([]RepoUsage, error)
	// Search runs an AQL items query: the matching items in the query's
	// order (then by ID), after its offset and within its limit, or within
	// o.Limit when it has none. Hits carry their properties only when the
	// query includes them. Every backend returns the same rows in the same
	// order as aql.Select.
	Search(ctx context.Context, q *aql.Query, o aql.Options) ([]aql.Hit, error)

	// Properties returns the item's properties (empty when it has none).
	// This and the other property and statistics methods return ErrNotFound
	// for a missing item. A key given with no values is not stored.
	//
	// SetProperties and PatchProperties take the time of the write, at. A
	// write that changes the properties sets the item's PropertiesModified to at,
	// or to zero when it leaves none; a write that changes nothing leaves it
	// alone, as Artifactory 6.20 touches its node_meta_infos row only when
	// PropertiesService.setProperties reports a change.
	Properties(ctx context.Context, id int64) (types.Properties, error)
	// SetProperties replaces all of the item's properties.
	SetProperties(ctx context.Context, id int64, props types.Properties, at time.Time) error
	// PatchProperties removes the keys in remove, then replaces the values of
	// the keys in set (so a key in both ends with the set values), leaving
	// other keys alone.
	PatchProperties(
		ctx context.Context, id int64, set types.Properties, remove []string, at time.Time,
	) error

	// Stats returns the item's statistics, zero when nothing was recorded.
	Stats(ctx context.Context, id int64) (types.ItemStats, error)
	// RecordDownload counts one download.
	RecordDownload(ctx context.Context, id int64, d Download) error
	// PutStats replaces the statistics, for import and federation sync.
	PutStats(ctx context.Context, id int64, s types.ItemStats) error
}

ItemStore persists items in the canonical form of decision 0004, with their properties and download statistics. An item's natural key is (RepoKey, Cached, Path, Name); its ID is assigned by the store. Paths are repository-relative without a leading slash; "" and "." both name the repository root.

A repository root has a record (types.RootItem) once properties are set on it, so they are kept and found by item ID like any item's. Only Root, EnsureRoot, GetByID and Search return it; Get, Children, Descendants, FindByChecksum and Usage leave it out, as does the result of Delete.

type KeyStore

type KeyStore interface {
	// CreateKeypair stores k; ErrConflict when the name exists.
	CreateKeypair(ctx context.Context, k types.Keypair) error
	// Keypair returns the key pair called name.
	Keypair(ctx context.Context, name string) (types.Keypair, error)
	// Keypairs returns every key pair ordered by name.
	Keypairs(ctx context.Context) ([]types.Keypair, error)
	// UpdateKeypair replaces a key pair.
	UpdateKeypair(ctx context.Context, k types.Keypair) error
	// DeleteKeypair removes a key pair. Refusing to remove one a repository
	// still uses (RepoStore.UsingKeypair) is the caller's decision.
	DeleteKeypair(ctx context.Context, name string) error

	// PutCertificate creates or replaces the certificate with c.Alias.
	PutCertificate(ctx context.Context, c types.Certificate) error
	// Certificate returns the certificate with alias.
	Certificate(ctx context.Context, alias string) (types.Certificate, error)
	// Certificates returns every certificate ordered by alias.
	Certificates(ctx context.Context) ([]types.Certificate, error)
	// DeleteCertificate removes a certificate.
	DeleteCertificate(ctx context.Context, alias string) error

	// CreateTrustedKey stores k; ErrConflict when the kid or alias exists.
	CreateTrustedKey(ctx context.Context, k types.TrustedKey) error
	// TrustedKey returns the trusted key with kid.
	TrustedKey(ctx context.Context, kid string) (types.TrustedKey, error)
	// TrustedKeys returns every trusted key ordered by kid.
	TrustedKeys(ctx context.Context) ([]types.TrustedKey, error)
	// DeleteTrustedKey removes a trusted key.
	DeleteTrustedKey(ctx context.Context, kid string) error

	// PutSigningKey creates or replaces the signing key with k.Alias. A key
	// stored with IsDefault clears the flag on every other key.
	PutSigningKey(ctx context.Context, k types.SigningKey) error
	// SigningKey returns the signing key with alias.
	SigningKey(ctx context.Context, alias string) (types.SigningKey, error)
	// SigningKeys returns every signing key ordered by alias.
	SigningKeys(ctx context.Context) ([]types.SigningKey, error)
	// DefaultSigningKey returns the key marked IsDefault.
	DefaultSigningKey(ctx context.Context) (types.SigningKey, error)
	// DeleteSigningKey removes a signing key.
	DeleteSigningKey(ctx context.Context, alias string) error
}

KeyStore persists key material: repository key pairs, trusted CA certificates, trusted release-bundle keys and Distribution signing keys. Private keys and passphrases are sealed.

type LeaseStore

type LeaseStore interface {
	// Acquire takes the lease l.Name for l.Holder until l.Expires when it is
	// free, expired at now, or already held by l.Holder (a renewal), and
	// reports whether it did. The stored lease is l as given, so a renewal
	// that wants to keep its acquisition time passes it back. ErrInvalid
	// when the name, holder or expiry is missing.
	Acquire(ctx context.Context, l types.Lease, now time.Time) (bool, error)
	// Release gives up a lease held by holder; releasing a lease someone
	// else holds, or nobody does, changes nothing.
	Release(ctx context.Context, name, holder string) error
	// List returns every lease ordered by name.
	List(ctx context.Context) ([]types.Lease, error)
}

LeaseStore persists named leases on background work.

type OutboxStore

type OutboxStore interface {
	// Append stores e as the next entry of (e.Origin, e.Stream) and returns
	// it with Seq assigned, one more than the stream's last. Call it inside
	// the transaction that makes the change it records; concurrent appends
	// to one stream are serialised, never given the same Seq.
	Append(ctx context.Context, e types.OutboxEntry) (types.OutboxEntry, error)
	// Read returns up to limit entries of a stream with Seq above after, in
	// Seq order.
	Read(
		ctx context.Context,
		origin, stream string,
		after int64,
		limit int,
	) ([]types.OutboxEntry, error)
	// LastSeq returns the highest Seq of a stream, 0 when it has none.
	LastSeq(ctx context.Context, origin, stream string) (int64, error)
	// Streams returns the streams origin has entries or a sequence in,
	// ordered.
	Streams(ctx context.Context, origin string) ([]string, error)
	// Prune removes entries of a stream with Seq at most upTo and returns how
	// many. The stream's sequence is not reset.
	Prune(ctx context.Context, origin, stream string, upTo int64) (int64, error)

	// PutCursor creates or replaces a peer's position in a stream.
	PutCursor(ctx context.Context, c types.PeerCursor) error
	// Cursor returns a peer's position in a stream.
	Cursor(ctx context.Context, peer, stream string) (types.PeerCursor, error)
	// Cursors returns a peer's positions ("" for every peer) ordered by
	// (peer, stream).
	Cursors(ctx context.Context, peer string) ([]types.PeerCursor, error)
	// DeleteCursors removes every position of a peer; a peer with none is
	// not an error.
	DeleteCursors(ctx context.Context, peer string) error

	// Applied returns the receiver's position in a peer's stream; a zero
	// LastSeq and no error when nothing was applied yet.
	Applied(ctx context.Context, origin, stream string) (types.AppliedMarker, error)
	// SetApplied records the position, in the transaction that applies the
	// entry, which is what makes applying idempotent.
	SetApplied(ctx context.Context, m types.AppliedMarker) error

	// RecordFailedFetch stores a failed blob fetch with Failures 1, or
	// increments Failures and replaces LastError of the existing one, keeping
	// its other fields, and returns the record as stored. Failures counts
	// the calls; the value in f is ignored.
	RecordFailedFetch(ctx context.Context, f types.FailedBlobFetch) (types.FailedBlobFetch, error)
	// FailedFetches returns a stream's failed fetches ("" for every stream)
	// ordered by (stream, sha256).
	FailedFetches(ctx context.Context, stream string) ([]types.FailedBlobFetch, error)
	// ClearFailedFetch removes one after a successful retry; ErrNotFound
	// when there is none.
	ClearFailedFetch(ctx context.Context, stream, sha256 string) error
}

OutboxStore persists the ordered event streams of decision 0021: this instance's outbox, each peer's acknowledged position in it, the receiver's applied positions, and blob fetches that failed while applying.

type PackageStore

type PackageStore interface {
	// Ensure returns the package (p.RepoKey, p.Name), creating it from p
	// when absent.
	Ensure(ctx context.Context, p types.Package) (types.Package, error)
	// Get returns the package with id.
	Get(ctx context.Context, id int64) (types.Package, error)
	// Find returns the package called name in repoKey.
	Find(ctx context.Context, repoKey, name string) (types.Package, error)
	// List returns a repository's packages ordered by name.
	List(ctx context.Context, repoKey string, p Page) ([]types.Package, string, error)
	// Delete removes the package with its versions and file links.
	Delete(ctx context.Context, id int64) error

	// PutVersion creates or replaces version (v.PackageID, v.Version), then
	// recomputes OrderKey for every version of the package with the
	// package type's comparator (types.ComparatorFor), and returns v as
	// stored.
	PutVersion(ctx context.Context, v types.PackageVersion) (types.PackageVersion, error)
	// Version returns one version of a package.
	Version(ctx context.Context, packageID int64, version string) (types.PackageVersion, error)
	// Versions returns a package's versions ordered by OrderKey, then
	// version string.
	Versions(ctx context.Context, packageID int64) ([]types.PackageVersion, error)
	// DeleteVersion removes a version and its file links and recomputes the
	// order keys of the rest.
	DeleteVersion(ctx context.Context, id int64) error
	// LinkFile records that an item belongs to a version; linking twice is
	// not an error. ErrNotFound when the version or the item is missing.
	LinkFile(ctx context.Context, f types.VersionFile) error
	// Files returns the item IDs of a version, ordered.
	Files(ctx context.Context, versionID int64) ([]int64, error)
	// VersionOf returns the version an item belongs to, the one with the
	// lowest ID when several link it.
	VersionOf(ctx context.Context, itemID int64) (types.PackageVersion, error)
	// RecordVersionDownload sets the version's LastDownloaded.
	RecordVersionDownload(ctx context.Context, versionID int64, at time.Time) error
}

PackageStore persists the package index of decision 0018.

type Page

type Page struct {
	After string
	Limit int
}

Page selects one page of a list. After is the next value returned with the previous page ("" for the first page). Limit bounds the page: DefaultLimit when zero or negative, capped at MaxLimit.

func (Page) Key

func (p Page) Key(n int) ([]string, error)

Key decodes After into the n parts of the sort key it continues after. It returns nil for the first page and ErrInvalidCursor when After does not carry exactly n parts, which is what a cursor from a different list looks like.

func (Page) Normalize

func (p Page) Normalize() (Page, error)

Normalize applies the default and maximum limit and checks that After decodes.

type PeerFilter

type PeerFilter struct {
	UseCase types.UseCase
}

PeerFilter narrows peer listings.

type PeerStore

type PeerStore interface {
	// Put creates or replaces the peer with p.InstanceID. UseCases are a
	// set: duplicates are dropped and Get and List return them sorted.
	Put(ctx context.Context, p types.Peer) error
	// Get returns the peer.
	Get(ctx context.Context, instanceID string) (types.Peer, error)
	// List returns matching peers ordered by instance ID.
	List(ctx context.Context, f PeerFilter) ([]types.Peer, error)
	// Delete removes the peer.
	Delete(ctx context.Context, instanceID string) error

	// AddNonce stores an issued pairing nonce; ErrConflict when its hash
	// exists.
	AddNonce(ctx context.Context, n types.PairingNonce) error
	// RedeemNonce marks the nonce redeemed at now and returns it. A nonce is
	// single-use: ErrNotFound when unknown or expired at now, ErrConflict
	// when already redeemed.
	RedeemNonce(ctx context.Context, hash []byte, now time.Time) (types.PairingNonce, error)
	// PruneNonces removes nonces that expired before t and returns how many.
	PruneNonces(ctx context.Context, before time.Time) (int64, error)
}

PeerStore persists paired peers and outstanding pairing nonces.

type PermissionStore

type PermissionStore interface {
	// Create stores p; ErrConflict when the name exists.
	Create(ctx context.Context, p types.Permission) error
	// Get returns the permission.
	Get(ctx context.Context, name string) (types.Permission, error)
	// Update replaces the permission.
	Update(ctx context.Context, p types.Permission) error
	// Delete removes the permission.
	Delete(ctx context.Context, name string) error
	// List returns permissions ordered by name.
	List(ctx context.Context, p Page) ([]types.Permission, string, error)
	// ForPrincipal returns the permissions that grant any action to user or
	// to any of groups, ordered by name.
	ForPrincipal(ctx context.Context, user string, groups []string) ([]types.Permission, error)
	// WithTarget returns the permissions naming target (a repository key, a
	// build repository, or an ANY target) in any resource, ordered by name.
	WithTarget(ctx context.Context, target string) ([]types.Permission, error)
}

PermissionStore persists permissions in the Access v2 shape (decision 0006). Grants and targets are mirrored into their own tables so the authorizer looks permissions up by principal and by target.

type PlatformStore

type PlatformStore interface {
	// PutAccessTarget creates or replaces the target with t.Name.
	PutAccessTarget(ctx context.Context, t types.AccessFederationTarget) error
	// AccessTarget returns one target.
	AccessTarget(ctx context.Context, name string) (types.AccessFederationTarget, error)
	// AccessTargets returns every target ordered by name.
	AccessTargets(ctx context.Context) ([]types.AccessFederationTarget, error)
	// DeleteAccessTarget removes a target.
	DeleteAccessTarget(ctx context.Context, name string) error

	// PutFederation creates or replaces the federation with f.ID.
	PutFederation(ctx context.Context, f types.PlatformFederation) error
	// Federation returns one federation.
	Federation(ctx context.Context, id string) (types.PlatformFederation, error)
	// Federations returns every federation ordered by ID.
	Federations(ctx context.Context) ([]types.PlatformFederation, error)
	// DeleteFederation removes a federation.
	DeleteFederation(ctx context.Context, id string) error

	// PutTopology creates or replaces the topology with t.Key and its sites;
	// ErrConflict when two sites share a name.
	PutTopology(ctx context.Context, t types.Topology) error
	// Topology returns one topology with its sites ordered by site name.
	Topology(ctx context.Context, key string) (types.Topology, error)
	// Topologies returns every topology ordered by key.
	Topologies(ctx context.Context) ([]types.Topology, error)
	// DeleteTopology removes a topology and its sites.
	DeleteTopology(ctx context.Context, key string) error
}

PlatformStore persists Access Federation targets, platform federations and topologies (decision 0025).

type PolicyFilter

type PolicyFilter struct {
	ItemType   types.CleanupItemType
	ProjectKey string
}

PolicyFilter narrows cleanup policy listings.

type ProjectStore

type ProjectStore interface {
	// Create stores p; ErrConflict when the key exists.
	Create(ctx context.Context, p types.Project) error
	// Get returns the project.
	Get(ctx context.Context, key string) (types.Project, error)
	// Update replaces the project.
	Update(ctx context.Context, p types.Project) error
	// Delete removes the project with its roles, environments, members,
	// the assignments of repositories it owns and its shares of others.
	Delete(ctx context.Context, key string) error
	// List returns every project ordered by key.
	List(ctx context.Context) ([]types.Project, error)

	// PutRole creates or replaces the role (r.ProjectKey, r.Name).
	PutRole(ctx context.Context, r types.Role) error
	// Role returns one role.
	Role(ctx context.Context, projectKey, name string) (types.Role, error)
	// Roles returns a project's roles, or the global ones for "", by name.
	Roles(ctx context.Context, projectKey string) ([]types.Role, error)
	// DeleteRole removes a role.
	DeleteRole(ctx context.Context, projectKey, name string) error

	// CreateEnvironment stores e. Environment names are unique across the
	// instance, global and project alike, so ErrConflict when the name is
	// taken anywhere.
	CreateEnvironment(ctx context.Context, e types.Environment) error
	// Environments returns a project's environments, or the global ones for
	// "", by name.
	Environments(ctx context.Context, projectKey string) ([]types.Environment, error)
	// RenameEnvironment renames an environment and every reference to it in
	// roles and repository assignments; ErrConflict when to is taken.
	RenameEnvironment(ctx context.Context, projectKey, from, to string) error
	// DeleteEnvironment removes an environment.
	DeleteEnvironment(ctx context.Context, projectKey, name string) error

	// PutMember creates or replaces a membership.
	PutMember(ctx context.Context, m types.ProjectMember) error
	// Member returns one membership.
	Member(
		ctx context.Context, projectKey string, typ types.PrincipalType, name string,
	) (types.ProjectMember, error)
	// Members returns a project's members of one principal type by name.
	Members(
		ctx context.Context, projectKey string, typ types.PrincipalType,
	) ([]types.ProjectMember, error)
	// DeleteMember removes a membership.
	DeleteMember(ctx context.Context, projectKey string, typ types.PrincipalType, name string) error

	// PutAssignment creates or replaces a repository's assignment and
	// shares. SharedWith comes back sorted and without duplicates.
	PutAssignment(ctx context.Context, a types.RepositoryAssignment) error
	// Assignment returns a repository's assignment.
	Assignment(ctx context.Context, repoKey string) (types.RepositoryAssignment, error)
	// Assignments returns the assignments of repositories assigned to or
	// shared with projectKey (including shared with all), by repository
	// key.
	Assignments(ctx context.Context, projectKey string) ([]types.RepositoryAssignment, error)
	// DeleteAssignment removes a repository's assignment and shares.
	DeleteAssignment(ctx context.Context, repoKey string) error
}

ProjectStore persists projects with their roles, environments, members and repository assignments. Global roles and environments are those with an empty ProjectKey. Writes that name a project (a project role or environment, a membership, an assignment's owner) return ErrNotFound when that project does not exist.

type ReplicaCount

type ReplicaCount struct {
	Member string
	State  types.ReplicaState
	Count  int64
	Bytes  int64
}

ReplicaCount is one member's number of replicas in one state and their combined size, for the storage summary.

type ReplicaFilter

type ReplicaFilter struct {
	Member string
	States []types.ReplicaState
}

ReplicaFilter narrows replica listings; empty fields match everything.

type ReplicaIndex

type ReplicaIndex interface {
	// Put creates or replaces the record (r.SHA256, r.Member); ErrInvalid
	// without both.
	Put(ctx context.Context, r types.BlobReplica) error
	// Get returns one record.
	Get(ctx context.Context, sha256, member string) (types.BlobReplica, error)
	// ForBlob returns a blob's records ordered by member.
	ForBlob(ctx context.Context, sha256 string) ([]types.BlobReplica, error)
	// List returns matching records oldest update first, by (Updated, SHA256,
	// Member), which is the order the repair worker drains them in.
	List(ctx context.Context, f ReplicaFilter, p Page) ([]types.BlobReplica, string, error)
	// Delete removes one record.
	Delete(ctx context.Context, sha256, member string) error
	// DeleteBlob removes every record of a blob and returns how many.
	DeleteBlob(ctx context.Context, sha256 string) (int64, error)
	// Counts returns the number and size of records per member and state,
	// ordered by (member, state).
	Counts(ctx context.Context) ([]ReplicaCount, error)
	// UnderReplicated counts the blobs with fewer than redundancy present
	// records. A blob with a deleting record is being deleted and is not
	// counted; neither is a blob with no records at all, which the repair
	// worker's backfill brings into the index.
	UnderReplicated(ctx context.Context, redundancy int) (int64, error)
	// SoleCopies counts, per member, the blobs whose only present record is
	// on that member. Blobs being deleted are left out, as UnderReplicated
	// leaves them out. A member holding sole copies cannot be removed from
	// a mirror without losing them: repair never reads from a member that
	// is no longer configured.
	SoleCopies(ctx context.Context) (map[string]int64, error)
}

ReplicaIndex records which mirror members hold which blobs (decision 0028): the blob_replicas table, and cold_blob_replicas for the archive tier.

type ReplicationStore

type ReplicationStore interface {
	// Put creates or replaces the replication with r.Key; ErrInvalid when
	// the key is empty.
	Put(ctx context.Context, r types.Replication) error
	// Get returns the replication with key.
	Get(ctx context.Context, key string) (types.Replication, error)
	// ForRepo returns a repository's replications ordered by key.
	ForRepo(ctx context.Context, repoKey string) ([]types.Replication, error)
	// List returns every replication ordered by (repository, key).
	List(ctx context.Context) ([]types.Replication, error)
	// Delete removes a replication and its runs.
	Delete(ctx context.Context, key string) error
	// DeleteForRepo removes every replication of a repository.
	DeleteForRepo(ctx context.Context, repoKey string) error
	// PutRun creates or replaces the run (r.ReplicationKey, r.Started);
	// ErrNotFound when the replication does not exist.
	PutRun(ctx context.Context, r types.ReplicationRun) error
	// LastRun returns a replication's most recent run.
	LastRun(ctx context.Context, key string) (types.ReplicationRun, error)
}

ReplicationStore persists replication targets and their run history. The replication key is assigned by the caller; the password is sealed.

type RepoFilter

type RepoFilter struct {
	Class       repo.Class
	PackageType repo.PackageType
	ProjectKey  string
}

RepoFilter narrows repository listings; empty fields match everything.

type RepoStore

type RepoStore interface {
	// Create stores c; ErrConflict when the key exists.
	Create(ctx context.Context, c repo.Config) error
	// Get returns the configuration, password included.
	Get(ctx context.Context, key string) (repo.Config, error)
	// Update replaces the stored configuration; ErrNotFound when absent.
	Update(ctx context.Context, c repo.Config) error
	// Delete removes the configuration only. Content is removed through
	// ItemStore.Delete and the package index through PackageStore.
	Delete(ctx context.Context, key string) error
	// List returns every matching repository ordered by key. Artifactory
	// lists repositories unpaged, so this does too.
	List(ctx context.Context, f RepoFilter) ([]repo.Config, error)
	// Including returns the keys of the virtual repositories that list key
	// as a member, ordered.
	Including(ctx context.Context, key string) ([]string, error)
	// UsingKeypair returns the keys of repositories whose primary or
	// secondary key pair is name, ordered.
	UsingKeypair(ctx context.Context, name string) ([]string, error)
}

RepoStore persists repository configurations. The remote password is sealed in its own column; the virtual member list and the key pair references are mirrored into tables so Including and UsingKeypair are indexed lookups.

type RepoUsage

type RepoUsage struct {
	RepoKey string
	Cached  bool
	Files   int64
	Folders int64
	Bytes   int64
}

RepoUsage is one repository's (or one remote cache's) content totals for the storage summary.

type RunFilter

type RunFilter struct {
	PolicyKey string
	ItemType  types.CleanupItemType
	Statuses  []types.RunStatus
}

RunFilter narrows cleanup run listings.

type SettingsStore

type SettingsStore interface {
	// Get decodes the value stored under key into into; ErrNotFound when
	// nothing is stored, which callers read as "use the default".
	Get(ctx context.Context, key string, into any) error
	// Put stores v under key, replacing any value.
	Put(ctx context.Context, key string, v any) error
	// Delete removes the value, restoring the default; ErrNotFound when
	// nothing was stored.
	Delete(ctx context.Context, key string) error
	// Keys returns the keys with stored values, ordered.
	Keys(ctx context.Context) ([]string, error)
}

SettingsStore persists the singleton settings (types.Setting* keys) as JSON values.

type Store

type Store interface {
	Repos() RepoStore
	Items() ItemStore
	Blobs() BlobIndex
	Replicas() ReplicaIndex
	Uploads() UploadStore
	Trash() TrashStore
	Packages() PackageStore

	Users() UserStore
	Groups() GroupStore
	Permissions() PermissionStore
	Tokens() TokenStore
	Keys() KeyStore

	Projects() ProjectStore
	Webhooks() WebhookStore
	Cleanup() CleanupStore
	Replications() ReplicationStore
	Settings() SettingsStore
	Leases() LeaseStore
	WorkQueue() WorkQueue
	Configs() ConfigStore

	Instance() InstanceStore
	Peers() PeerStore
	Outbox() OutboxStore
	Federation() FederationStore
	Platform() PlatformStore

	Bundles() BundleStore
	Distribution() DistributionStore
	Archive() ArchiveStore
	Workers() WorkerStore

	Builds() BuildStore

	// Tx runs fn in one transaction. Store calls made with the context fn
	// receives take part; an error from fn rolls all of them back. A nested
	// Tx joins the outer transaction.
	Tx(ctx context.Context, fn func(ctx context.Context) error) error
	// AfterCommit defers fn until the enclosing transaction commits, or runs
	// it at once outside a transaction. Nothing runs after a rollback.
	AfterCommit(ctx context.Context, fn func())
	// Close releases resources.
	Close() error
}

Store is the complete metadata persistence surface.

type TokenFilter

type TokenFilter struct {
	Subject string
	// Purpose, when set, lists only tokens of that purpose.
	Purpose string
}

TokenFilter narrows token listings.

type TokenStore

type TokenStore interface {
	// Create stores t; ErrConflict when the ID or a digest exists, or when
	// the subject already has a token of t's purpose.
	Create(ctx context.Context, t types.Token) error
	// Get returns the token with id.
	Get(ctx context.Context, id string) (types.Token, error)
	// ByDigest returns the token whose digest of the given kind is digest,
	// which is how revocation by value and refresh find the record.
	ByDigest(ctx context.Context, kind DigestKind, digest []byte) (types.Token, error)
	// List returns tokens ordered by (IssuedAt, ID).
	List(ctx context.Context, f TokenFilter, p Page) ([]types.Token, string, error)
	// Delete removes the token, revoking it.
	Delete(ctx context.Context, id string) error
	// Touch sets LastUsed.
	Touch(ctx context.Context, id string, at time.Time) error
	// DeleteExpired removes tokens that expired before t and returns how
	// many; tokens that never expire are kept.
	DeleteExpired(ctx context.Context, before time.Time) (int64, error)
}

TokenStore persists access token records. The tokens themselves are never stored, except a purposed token's Secret, which stores seal.

type TrashStore

type TrashStore interface {
	// Add stores e and returns it with its assigned ID.
	Add(ctx context.Context, e types.TrashEntry) (types.TrashEntry, error)
	// Get returns the entry with id.
	Get(ctx context.Context, id int64) (types.TrashEntry, error)
	// Find returns the entries for an original repository and full path,
	// newest first (entries without a deletion time last). A path that does
	// not split into parent and name matches nothing.
	Find(ctx context.Context, repoKey, fullPath string) ([]types.TrashEntry, error)
	// List returns entries from repoKey ("" for every repository) whose
	// original full path is prefix or below it ("" for all), ordered by
	// (repository, path, name, ID).
	List(ctx context.Context, repoKey, prefix string, p Page) ([]types.TrashEntry, string, error)
	// Delete removes an entry.
	Delete(ctx context.Context, id int64) error
	// Expired returns entries deleted before t, oldest first, at most limit
	// (DefaultLimit when zero).
	Expired(ctx context.Context, before time.Time, limit int) ([]types.TrashEntry, error)
}

TrashStore persists the trash can.

type Upload

type Upload struct {
	ID      string
	Backend string
	RepoKey string
	Path    string
	State   []byte
	Bytes   int64
	Started time.Time
	Updated time.Time
}

Upload is a blob upload session that outlives one request: a Docker chunked upload, the CLI's multipart upload, or an S3 multipart session. State is the blob backend's own session record, opaque here.

type UploadStore

type UploadStore interface {
	// Put creates or replaces the session with u.ID.
	Put(ctx context.Context, u Upload) error
	// Get returns the session.
	Get(ctx context.Context, id string) (Upload, error)
	// Delete removes the session.
	Delete(ctx context.Context, id string) error
	// Stale lists sessions last updated (or started, when never updated)
	// before t, oldest first, at most limit (DefaultLimit when zero), for
	// the reaper.
	Stale(ctx context.Context, before time.Time, limit int) ([]Upload, error)
}

UploadStore persists upload sessions.

type UserStore

type UserStore interface {
	// Create stores u and its memberships; ErrConflict when the name exists,
	// ErrNotFound when a named group does not.
	Create(ctx context.Context, u types.User) error
	// Get returns the user with Groups sorted.
	Get(ctx context.Context, name string) (types.User, error)
	// Update replaces the user's fields and memberships.
	Update(ctx context.Context, u types.User) error
	// Delete removes the user and its memberships.
	Delete(ctx context.Context, name string) error
	// List returns users ordered by name.
	List(ctx context.Context, p Page) ([]types.User, string, error)
	// RecordLogin sets LastLoggedIn and resets FailedLogins.
	RecordLogin(ctx context.Context, name string, at time.Time) error
	// RecordFailedLogin adds one to FailedLogins in one atomic step and,
	// when lockAt is positive and the count reaches it, sets an enabled
	// user's Status to locked. It reports whether the user is locked
	// afterwards. ErrNotFound when the user does not exist.
	RecordFailedLogin(ctx context.Context, name string, lockAt int) (bool, error)
	// Unlock sets locked users among names back to enabled and resets
	// their FailedLogins; with no names it unlocks every locked user.
	// Unknown names are ignored.
	Unlock(ctx context.Context, names ...string) error
	// Locked returns the names of locked users, ordered.
	Locked(ctx context.Context) ([]string, error)
}

UserStore persists users. A user's Groups are its memberships, kept in the group_members table shared with GroupStore.

type WebhookFilter

type WebhookFilter struct {
	Domain      types.WebhookDomain
	ProjectKey  string
	EnabledOnly bool
}

WebhookFilter narrows subscription listings.

type WebhookStore

type WebhookStore interface {
	// Create stores w; ErrConflict when the key exists.
	Create(ctx context.Context, w types.WebhookSubscription) error
	// Get returns the subscription, secrets included.
	Get(ctx context.Context, key string) (types.WebhookSubscription, error)
	// Update replaces the subscription.
	Update(ctx context.Context, w types.WebhookSubscription) error
	// Delete removes the subscription and its delivery records.
	Delete(ctx context.Context, key string) error
	// List returns matching subscriptions ordered by key.
	List(ctx context.Context, f WebhookFilter) ([]types.WebhookSubscription, error)
	// AddDelivery records a delivery attempt and returns it with its ID;
	// ErrNotFound when the subscription does not exist.
	AddDelivery(ctx context.Context, d types.WebhookDelivery) (types.WebhookDelivery, error)
	// Deliveries returns matching records newest first, at most f.Limit
	// (DefaultLimit when zero).
	Deliveries(ctx context.Context, f DeliveryFilter) ([]types.WebhookDelivery, error)
	// PruneDeliveries removes records attempted before t and returns how
	// many.
	PruneDeliveries(ctx context.Context, before time.Time) (int64, error)
}

WebhookStore persists event subscriptions and their delivery records. Handler secrets are sealed.

type WorkFailure

type WorkFailure struct {
	Error string
	// RetryAt is when the item is due again unless parked.
	RetryAt time.Time
	// Park stops retrying until the key is enqueued again.
	Park bool
	Now  time.Time
}

WorkFailure is how a run ended unsuccessfully.

type WorkLease

type WorkLease struct {
	// Kinds limits Lease to these kinds; empty takes any.
	Kinds  []string
	Holder string
	// Limit is the most items Lease takes; LeaseKey ignores it.
	Limit int
	// Until is when the lease runs out unless extended; Now is when it is
	// taken.
	Until, Now time.Time
}

WorkLease is what a worker asks the queue for.

type WorkQueue

type WorkQueue interface {
	// Enqueue asks for the work kind names for key, with payload (a small
	// JSON document, or empty). Called inside the caller's transaction, it
	// commits or rolls back with the change that needs the work.
	//   - A key with no item gets a pending one, due now.
	//   - A pending key keeps its schedule and takes the new payload.
	//   - A leased key takes the new payload and is marked to run once more
	//     when its current run ends.
	//   - A parked key is pending again from now, its attempts reset.
	// ErrInvalid for an empty or overlong kind or key, or a payload that is
	// not JSON or exceeds MaxWorkPayload.
	Enqueue(ctx context.Context, kind, key string, payload []byte, now time.Time) error
	// Lease takes up to req.Limit due items of req.Kinds (every kind when
	// empty) for req.Holder until req.Until: pending items from their
	// NotBefore on, and leased items whose lease ran out, the longest due
	// first. Each taken item's Generation and Attempts go up by one and its
	// DirtySince clears, since the new run covers that work. Concurrent
	// callers never take the same item.
	Lease(ctx context.Context, req WorkLease) ([]types.WorkItem, error)
	// LeaseKey takes the item of kind and key, as Lease would, when it is
	// pending (whatever its NotBefore) or its lease ran out, so a reader
	// can bring derived data up to date before using it. It returns the
	// item as it stands and whether it was taken. ErrNotFound when there is
	// no item.
	LeaseKey(ctx context.Context, kind, key string, req WorkLease) (types.WorkItem, bool, error)
	// Extend moves the lease of the run with generation gen to until.
	// ErrConflict when that run no longer holds the item.
	Extend(ctx context.Context, kind, key string, gen int64, until, now time.Time) error
	// Complete ends the run with generation gen successfully. The item is
	// deleted, or, when work was asked for again during the run, pending
	// again from now with its attempts reset. ErrConflict when the run no
	// longer holds the item.
	Complete(ctx context.Context, kind, key string, gen int64, now time.Time) error
	// Fail ends the run with generation gen unsuccessfully: pending again
	// from f.RetryAt, or parked when f.Park and no work was asked for during
	// the run. ErrConflict when the run no longer holds the item.
	Fail(ctx context.Context, kind, key string, gen int64, f WorkFailure) error
	// Release hands back the run with generation gen unfinished, as a
	// stopping worker does: pending again from now, without counting the
	// attempt. ErrConflict when the run no longer holds the item.
	Release(ctx context.Context, kind, key string, gen int64, now time.Time) error
	// Get returns the item of kind and key; ErrNotFound when there is none.
	Get(ctx context.Context, kind, key string) (types.WorkItem, error)
	// Stats counts each kind's items by state, ordered by kind.
	Stats(ctx context.Context) ([]types.WorkStats, error)
}

WorkQueue persists asynchronous derived work (decision 0033): one item per kind and key, run by one worker at a time. Every method is given the time it acts at, so no backend reads a clock.

type WorkerFilter

type WorkerFilter struct {
	Action      types.WorkerAction
	ProjectKey  string
	EnabledOnly bool
}

WorkerFilter narrows worker listings.

type WorkerStore

type WorkerStore interface {
	// Create stores w; ErrConflict when the key exists.
	Create(ctx context.Context, w types.Worker) error
	// Get returns the worker.
	Get(ctx context.Context, key string) (types.Worker, error)
	// Update replaces the worker.
	Update(ctx context.Context, w types.Worker) error
	// Delete removes the worker with its state, secrets and executions.
	Delete(ctx context.Context, key string) error
	// List returns matching workers ordered by key.
	List(ctx context.Context, f WorkerFilter) ([]types.Worker, error)

	// State returns a worker's state entries; ErrNotFound when the worker
	// does not exist.
	State(ctx context.Context, worker string) (map[string]string, error)
	// SetState creates or replaces one entry; ErrNotFound when the worker
	// does not exist. The per-worker limits are the caller's to apply
	// (types.ValidateWorkerState).
	SetState(ctx context.Context, worker, key, value string) error
	// DeleteState removes one entry; removing a missing entry is not an
	// error.
	DeleteState(ctx context.Context, worker, key string) error

	// PutSecret creates or replaces a secret; ErrNotFound when the worker
	// does not exist.
	PutSecret(ctx context.Context, worker, name, value string) error
	// Secrets returns a worker's secrets by name; ErrNotFound when the
	// worker does not exist.
	Secrets(ctx context.Context, worker string) (map[string]string, error)
	// DeleteSecret removes a secret.
	DeleteSecret(ctx context.Context, worker, name string) error

	// AddExecution records an execution; ErrConflict when its ID exists,
	// ErrNotFound when its worker does not.
	AddExecution(ctx context.Context, e types.WorkerExecution) error
	// Execution returns one execution.
	Execution(ctx context.Context, id string) (types.WorkerExecution, error)
	// Executions returns a worker's executions ("" for every worker) newest
	// first, by (Started, ID).
	Executions(ctx context.Context, worker string, p Page) ([]types.WorkerExecution, string, error)
	// PruneExecutions removes executions started before t and returns how
	// many.
	PruneExecutions(ctx context.Context, before time.Time) (int64, error)
}

WorkerStore persists Workers (decision 0026) with their key-value state, sealed secrets and execution history.

Directories

Path Synopsis
Package inmem is the reference in-memory implementation of pkg/store.
Package inmem is the reference in-memory implementation of pkg/store.
Package storetest is the contract suite for pkg/store implementations (decision 0015).
Package storetest is the contract suite for pkg/store implementations (decision 0015).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL