integrity

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: May 15, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package integrity contains the bridge's proactive consistency watchers — long-lived goroutines that walk durable state on a schedule and reconcile drift between what the bridge thinks exists (SQLite manifest, track_variants table) and what actually exists on disk.

The library-source-file watcher lives in internal/manifest's Scanner.RunPeriodic (6 h default, plus optional fsnotify). The upscale-variant watcher lives here. Both pair with the equivalent reactive paths in internal/api (download serving stat-on-open; the manifest scanner's per-walk diff) — the schedulers handle the "operator did something while the bridge wasn't looking" cases.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type PublishFunc

type PublishFunc func(paths []string, variantIDs []string)

PublishFunc is the domain-specific publish callback fired once per sweep that observed at least one missing sidecar. The integrity package keeps the wire-shape construction at the cmd/bridge wiring layer so it can build the typed api.UpscaleDeletedEvent without an upward import cycle — the integrity package only knows "I observed these disappearances", not the broker's serialization concerns.

`paths` and `variantIDs` are positional but NOT zipped 1:1: callers treat them as the set of paths affected AND the set of variantIDs that disappeared somewhere in those paths. Same semantic the api.UpscaleDeletedEvent struct already documents.

type VariantDeleter

type VariantDeleter interface {
	DeleteVariant(sourcePath, variantID string) error
}

VariantDeleter removes one variant row by (source_path, variant_id). The Store's DeleteVariant transactionally bumps `tracks.indexed_at` so iOS delta-sync observes the removal on the next manifest fetch. Per-row error tolerance: a Watcher tick logs and continues on per-row failure, but still publishes the events for the rows that DID delete.

type VariantLister

type VariantLister interface {
	AllVariants() ([]VariantSnapshot, error)
}

VariantLister enumerates every row in the track_variants table. The watcher consumes the snapshot per tick and stats each sidecar path. Mirrors the manifest.Store method shape; cmd/bridge wires the adapter.

type VariantSnapshot

type VariantSnapshot struct {
	SourcePath  string
	VariantID   string
	SidecarPath string
}

VariantSnapshot is the integrity-package-local projection of one track_variants row. Mirrors `api.VariantSummary` but stays internal to integrity so the package doesn't import internal/api (which would create an upward dependency cycle — api consumes integrity events via the broker, not the other way round).

type VariantWatcher

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

VariantWatcher walks the track_variants table on a cadence configurable via cfg.Integrity.VariantSweepInterval (default 1 h) and reconciles rows whose sidecar file no longer exists on disk. Reasons a sidecar might disappear outside the bridge: operator `rm -rf <DataDir>/transcoded/`, backup software with eager retention, disk-image rebuild that preserved the SQLite DB but not the sidecar tree.

On every miss, the row is removed via the supplied Deleter (bumps `tracks.indexed_at` so iOS delta-sync sees the disappearance) AND a single batched `upscale.deleted` SSE event is published per tick — iOS reconciles immediately without waiting for a manifest re-sync.

Threading: one long-lived goroutine spun up by Start; stops on the supplied ctx's cancellation. Time.NewTicker is reset on every tick (we use a manual select loop) so the first sweep fires immediately at boot — closes the "operator deleted variant files while the bridge was down" case without waiting for the first interval to elapse.

func NewVariantWatcher

func NewVariantWatcher(lister VariantLister, deleter VariantDeleter, publish PublishFunc, interval time.Duration) *VariantWatcher

NewVariantWatcher constructs a watcher. interval ≤ 0 disables the watcher entirely — Start returns a no-op stopFn. Used by operators on minimal deploys who only run `--gc` manually.

func (*VariantWatcher) SetOnTickComplete

func (w *VariantWatcher) SetOnTickComplete(fn func(deletedCount int))

SetOnTickComplete is a test-only seam. Production wires nil. Same convention as transcode.Pool's SetOnStateChange — the test harness can register a callback once at construction without exposing internal channels.

func (*VariantWatcher) Start

func (w *VariantWatcher) Start(ctx context.Context) (stopFn func())

Start spins up the long-lived sweep goroutine and returns a stopFn the caller `defer`s on shutdown. The goroutine fires one immediate sweep at boot, then ticks every `interval`. A cancelled context AND the returned stopFn both cleanly stop the loop; either is sufficient (they're equivalent paths).

Idempotent: a duplicate Start returns a stopFn that closes the SAME `w.done` channel the active run goroutine is selecting on. Both `startOnce` and `stopOnce` live on the struct so a second Start's stopFn doesn't pointlessly close a fresh per-call channel the run loop never sees. Calling Start with interval ≤ 0 returns a no-op stopFn — no goroutine is spawned at all (avoids the per-process resource cost on minimal deploys).

Jump to

Keyboard shortcuts

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