store

package
v0.1.7 Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package store provides MySQL-backed metadata storage for the Epoch control plane.

MySQL serves as an index/cache over the object-store-backed registry. Object storage remains the source of truth for blobs; MySQL provides queryable metadata.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Blob

type Blob struct {
	Digest    string `json:"digest"`
	Size      int64  `json:"size"`
	MediaType string `json:"mediaType"`
	RefCount  int    `json:"refCount"`
}

Blob is a DB blob record.

type DashboardStats

type DashboardStats struct {
	RepositoryCount int   `json:"repositoryCount"`
	TagCount        int   `json:"tagCount"`
	BlobCount       int   `json:"blobCount"`
	TotalSize       int64 `json:"totalSize"`
}

DashboardStats holds aggregate stats for the UI dashboard.

type PlatformSize added in v0.1.7

type PlatformSize struct {
	Digest     string `json:"digest"`
	Size       int64  `json:"size"`
	LayerCount int    `json:"layerCount"`
}

PlatformSize is the standalone content size of one child manifest inside an OCI image index — i.e. config blob plus the sum of layer blobs as declared by that child, with no cross-platform deduplication. The natural answer to "if I only pulled this platform, how many bytes would I download".

type PlatformSizes added in v0.1.7

type PlatformSizes []PlatformSize

PlatformSizes is a slice of PlatformSize that round-trips through a MySQL JSON column transparently. Empty/nil persists as SQL NULL so non-index tags do not store a placeholder `[]`.

func (*PlatformSizes) Scan added in v0.1.7

func (p *PlatformSizes) Scan(src any) error

Scan implements sql.Scanner for reading back from a JSON column. NULL maps to a nil slice; the column is allowed to be string or []byte depending on driver flags.

func (PlatformSizes) Value added in v0.1.7

func (p PlatformSizes) Value() (driver.Value, error)

Value implements driver.Valuer for storing in a JSON column.

type Repository

type Repository struct {
	ID           int64     `json:"id"`
	Name         string    `json:"name"`
	TagCount     int       `json:"tagCount"`
	TotalSize    int64     `json:"totalSize"`
	ArtifactType string    `json:"artifactType,omitempty"`
	Kind         string    `json:"kind,omitempty"`
	CreatedAt    time.Time `json:"createdAt"`
	UpdatedAt    time.Time `json:"updatedAt"`
}

Repository is a DB repository record. ArtifactType / Kind reflect the most recently pushed tag in the repo so the UI can show the artifact flavor (cloud-image / snapshot / container-image) without making a separate per-tag round-trip.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store wraps a MySQL connection for Epoch metadata.

func New

func New(ctx context.Context, dsn string) (*Store, error)

New opens a MySQL connection and runs migrations.

func (*Store) Close

func (s *Store) Close() error

func (*Store) CreateToken

func (s *Store) CreateToken(ctx context.Context, name, createdBy string) (string, error)

func (*Store) DeleteTag

func (s *Store) DeleteTag(ctx context.Context, repoName, tagName string) error

func (*Store) DeleteToken

func (s *Store) DeleteToken(ctx context.Context, id int64) error

func (*Store) GetRepository

func (s *Store) GetRepository(ctx context.Context, name string) (*Repository, error)

func (*Store) GetStats

func (s *Store) GetStats(ctx context.Context) (*DashboardStats, error)

func (*Store) GetTag

func (s *Store) GetTag(ctx context.Context, repoName, tagName string) (*Tag, error)

func (*Store) InvalidateTokenCache added in v0.1.7

func (s *Store) InvalidateTokenCache()

InvalidateTokenCache clears all cached token validations.

func (*Store) ListRepositories

func (s *Store) ListRepositories(ctx context.Context) ([]Repository, error)

func (*Store) ListTags

func (s *Store) ListTags(ctx context.Context, repoName string) ([]Tag, error)

func (*Store) ListTokens

func (s *Store) ListTokens(ctx context.Context) ([]Token, error)

func (*Store) SyncFromCatalog

func (s *Store) SyncFromCatalog(ctx context.Context, reg *registry.Registry) error

SyncFromCatalog walks the registry catalog and ingests every (repo, tag) into MySQL. Each tag's manifest is parsed as OCI and indexed by digest, artifactType, and aggregate size. Orphaned rows (repos / tags that no longer appear in the catalog) are deleted in a second pass.

Sync is split into two phases so the write transaction never holds while epoch is talking to remote object storage:

  1. prepareSync — read existing tag state from MySQL, fetch + parse + aggregate every catalog tag from the registry. No write TX is open, so the seconds spent on S3 round-trips do not block concurrent writers (token last_used updates, tag deletes, etc).
  2. commitSync — open one short write TX and upsert every prepared repo / tag / blob. The lock window stays in milliseconds even when phase 1 took seconds.

Per-tag failures stay non-fatal so one bad manifest does not abort the whole pass. Context cancellation during phase 1 aborts the pass before any writes are issued.

func (*Store) ValidateToken

func (s *Store) ValidateToken(ctx context.Context, plaintext string) bool

type Tag

type Tag struct {
	ID            int64         `json:"id"`
	RepositoryID  int64         `json:"-"`
	RepoName      string        `json:"repoName,omitempty"`
	Name          string        `json:"name"`
	Digest        string        `json:"digest"`
	ArtifactType  string        `json:"artifactType,omitempty"`
	Kind          string        `json:"kind,omitempty"`
	ManifestJSON  string        `json:"-"`
	TotalSize     int64         `json:"totalSize"`
	LayerCount    int           `json:"layerCount"`
	PlatformSizes PlatformSizes `json:"platformSizes,omitempty"`
	PushedAt      time.Time     `json:"pushedAt"`
	SyncedAt      time.Time     `json:"syncedAt"`
}

Tag is a DB tag record. ArtifactType captures the OCI 1.1 manifest artifactType field (e.g. cocoonstack.snapshot.v1+json) so the UI can show whether a tag is a snapshot, cloud image, or container image without re-parsing the manifest JSON on every list call.

PlatformSizes is populated only for tags whose kind is image-index. Each entry is the standalone (config + sum(layers)) size of one child manifest, keyed by the child's content digest. Materialized at sync time so the tag detail API does not need to refetch every child manifest just to render per-platform sizes in the UI.

type Token

type Token struct {
	ID        int64      `json:"id"`
	Name      string     `json:"name"`
	Token     string     `json:"token,omitempty"`
	CreatedBy string     `json:"createdBy"`
	CreatedAt time.Time  `json:"createdAt"`
	LastUsed  *time.Time `json:"lastUsed,omitempty"`
}

Token is a registry access token. The Token field is only populated on create (returned to caller); it is never read back from the DB.

Jump to

Keyboard shortcuts

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