Documentation
¶
Index ¶
- Constants
- func ImageDimensions(root *os.Root, name string) (w, h int)
- func IsSyncedName(name string) bool
- func SyncedFilename(a Asset) string
- func ValidImageName(name string) bool
- type Advancer
- type AspectStore
- func (s *AspectStore) BackfillMissing(ctx context.Context, lib *Library) bool
- func (s *AspectStore) Delete(name string)
- func (s *AspectStore) Flush() error
- func (s *AspectStore) Missing(names []string) []string
- func (s *AspectStore) Ratio(name string) (ratio float64, ok bool)
- func (s *AspectStore) Set(name string, w, h int)
- type Asset
- type Image
- type Library
- func (l *Library) Add(name string)
- func (l *Library) Cycle() []Image
- func (l *Library) Has(name string) bool
- func (l *Library) Len() int
- func (l *Library) List() []Image
- func (l *Library) Randomized() bool
- func (l *Library) Remove(name string) bool
- func (l *Library) Reshuffle() []Image
- func (l *Library) SetOrder(names []string) []string
- func (l *Library) SetRandomize(enabled bool) bool
- type Option
- type OrderStore
- type RemoteAlbum
- type Status
- type Syncer
- type SyncerOption
- type SyncerStatus
Constants ¶
const ImageNamePattern = `^[a-zA-Z0-9_.~-]+\.(jpe?g|png)$`
ImageNamePattern is the canonical image filename rule; the HTTP routes embed it as a huma `pattern` tag (a test keeps them in sync).
Variables ¶
This section is empty.
Functions ¶
func ImageDimensions ¶ added in v1.1.0
ImageDimensions reads an image's pixel size from its header only (no full decode); returns 0,0 on any error.
func IsSyncedName ¶
IsSyncedName reports whether name matches the synced-file pattern.
func SyncedFilename ¶
SyncedFilename returns the canonical local name for an asset. Panics on an empty Version, which would produce an unparseable name and loop in the diff.
func ValidImageName ¶
ValidImageName reports whether name is servable by the /img/{name} route.
Types ¶
type Advancer ¶
type Advancer interface {
Next()
}
Advancer is poked when the syncer brings an empty library to non-empty.
type AspectStore ¶ added in v1.1.0
type AspectStore struct {
// contains filtered or unexported fields
}
AspectStore caches per-image aspect ratios as a JSON sidecar in the images directory, captured once at upload/sync so reads never decode. Safe for concurrent use.
func LoadAspectStore ¶ added in v1.1.0
LoadAspectStore reads the sidecar index from root (empty when absent).
func (*AspectStore) BackfillMissing ¶ added in v1.1.0
func (s *AspectStore) BackfillMissing(ctx context.Context, lib *Library) bool
BackfillMissing decodes and stores dimensions for any library image absent from the index, then persists once. Meant to run in the background at startup. It reports whether it recorded anything, so the caller can rebuild a plan that was built before the ratios were available.
func (*AspectStore) Delete ¶ added in v1.1.0
func (s *AspectStore) Delete(name string)
Delete drops name in memory; call Flush to persist.
func (*AspectStore) Flush ¶ added in v1.1.0
func (s *AspectStore) Flush() error
Flush writes the index atomically (tmp + rename) through the images root.
func (*AspectStore) Missing ¶ added in v1.1.0
func (s *AspectStore) Missing(names []string) []string
Missing returns the subset of names with no cached dimensions.
func (*AspectStore) Ratio ¶ added in v1.1.0
func (s *AspectStore) Ratio(name string) (ratio float64, ok bool)
Ratio returns the cached width/height for name; ok is false when the name is absent or has no usable height.
func (*AspectStore) Set ¶ added in v1.1.0
func (s *AspectStore) Set(name string, w, h int)
Set records dimensions for name in memory; call Flush to persist.
type Asset ¶
type Asset struct {
ID string // stable identity; used as the filename stem
Version string // opaque change token; a new value means re-download
}
Asset is one image in a RemoteAlbum.
type Image ¶
type Image struct {
Name string // filename only, e.g. "1716038400000.jpg"
}
Image represents a stored image file.
type Library ¶
type Library struct {
// contains filtered or unexported fields
}
Library maintains the canonical image order (admin source of truth) plus the current playback cycle, a shuffled copy when randomized. Safe for concurrent use.
func (*Library) Add ¶
Add appends a new image to the canonical order and the current cycle so it shows without waiting for a reshuffle.
func (*Library) Randomized ¶ added in v1.1.1
Randomized reports whether playback is shuffled.
func (*Library) Remove ¶
Remove deletes the first image with name from both slices; false if absent from the canonical order.
func (*Library) Reshuffle ¶ added in v1.1.0
Reshuffle starts a new playback cycle from the canonical order and returns a copy. Randomized cycles avoid repeating the previous cycle's last image first.
func (*Library) SetOrder ¶ added in v1.1.1
SetOrder reorders the canonical order to match names: unknown names are ignored and ones missing from names keep their relative order at the end (so a stale payload never drops a file). Returns the resulting names to persist.
func (*Library) SetRandomize ¶
SetRandomize toggles random playback and reports whether the value changed.
type Option ¶
type Option func(*Library)
Option defines a functional configuration for the Library.
func WithTestRNG ¶
WithTestRNG injects a deterministic random number generator for unit tests.
type OrderStore ¶ added in v1.1.1
type OrderStore struct {
// contains filtered or unexported fields
}
OrderStore persists the canonical image order as a JSON array sidecar in the images directory. Safe for concurrent use.
func LoadOrderStore ¶ added in v1.1.1
LoadOrderStore reads the saved order from root; returns nil names when absent or corrupt.
func (*OrderStore) Save ¶ added in v1.1.1
func (s *OrderStore) Save(names []string) error
Save writes the order atomically (tmp + rename) through the images root.
type RemoteAlbum ¶
type RemoteAlbum interface {
List(ctx context.Context) ([]Asset, error)
Fetch(ctx context.Context, id string) (io.ReadCloser, error)
}
RemoteAlbum is a read-only view of an album in a remote photo service.
type Syncer ¶
type Syncer struct {
// contains filtered or unexported fields
}
Syncer reconciles a RemoteAlbum with a local directory and Library on a tick. Files are named "<asset-id>-<version>.jpg" so an edit upstream (new version) becomes a new local file: old version deleted, new version downloaded.
func (*Syncer) Run ¶
Run syncs immediately then on each interval (or on Trigger) until ctx is cancelled.
type SyncerOption ¶ added in v1.1.0
type SyncerOption func(*Syncer)
SyncerOption configures optional Syncer collaborators.
func WithAspectStore ¶ added in v1.1.0
func WithAspectStore(a *AspectStore) SyncerOption
WithAspectStore records downloaded dimensions and clears them on removal.
type SyncerStatus ¶
type SyncerStatus interface {
Status() Status
Trigger()
}
SyncerStatus is the read-and-trigger surface over a Syncer. Callers that may hold no syncer (the fs backend) keep it behind this interface so a nil syncer reads as a nil interface rather than a typed-nil.