Documentation
¶
Overview ¶
Package prefetch warms the segment cache in the background so the next episode and the resume point of in-progress titles start instantly.
- Next episode: when a timeline update shows an episode past config.Cache.NextEpisodeAt, the next episode is resolved for the same client and its opening PrefetchBytes are pulled.
- Keep warm: periodically, a window around each in-progress title's resume point is pulled from the release that last served it.
All work runs on a bounded pool at core.PriorityPrefetch through Engine.Prefetch, is deduplicated, and never blocks the caller: OnTimeline only enqueues, and a full queue drops work rather than wait.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func WarmWindow ¶
func WarmWindow(viewOffset, duration time.Duration, size, behind, ahead int64) (start, length int64)
WarmWindow is the byte window kept warm for a resume point: behind bytes before the offset mapped from viewOffset (constant-bitrate mapping) and ahead bytes after it, clamped to the file.
Types ¶
type Deps ¶
type Deps struct {
Catalog core.Catalog
Resolver core.Resolver
Engine core.Engine
State core.State
Auth core.Auth
Hints Hints
Logger *slog.Logger
// PostPlay ranks the personalized hook queue (optional; #30). With
// it set, the end of a movie or season/series finale pre-buffers the
// #1 pick instead of relying on next-episode prefetch.
PostPlay core.PostPlayer
// Prewarmer warms the pick through the playback manager when it
// implements core.Prewarmer; nil falls back to resolve + Engine.Prefetch.
Prewarmer core.Prewarmer
// Markers supplies credits ranges through the markers service API
// (optional; without it the trigger is duration − 3 minutes).
Markers MarkerSource
// PostPlayEnabled reports the owner's switch (nil = on).
PostPlayEnabled func() bool
}
Deps are the prefetcher's collaborators. Catalog, Resolver and Engine are required; State, Auth and Hints enable keep-warm (and Hints the reuse of stored releases).
type Hints ¶
type Hints interface {
// ResumePoint is the release that last served a user's title.
ResumePoint(ctx context.Context, userID int64, key core.RatingKey) (*playback.ResumePoint, error)
// ResumeFor is the stored release a Prepare from this client would open.
ResumeFor(ctx context.Context, user *core.User, key core.RatingKey, caps core.ClientCaps) (*playback.ResumePoint, error)
// Remember stores a prefetched resolution so playback opens the same release.
Remember(ctx context.Context, user *core.User, key core.RatingKey, caps core.ClientCaps, res *core.Resolution) error
// ClientCaps returns the caps of the user's session for key (live) or
// of the user's latest session.
ClientCaps(userID int64, key core.RatingKey) (caps core.ClientCaps, live bool, ok bool)
}
Hints is what prefetch needs from playback; *playback.Manager implements it.
type MarkerSource ¶
type MarkerSource interface {
Markers(ctx context.Context, key core.RatingKey, info core.MediaInfo) ([]markers.Marker, error)
}
MarkerSource is the markers service API (internal/markers.Service satisfies it, as does plex.MarkerProvider).
type Options ¶
type Options struct {
// Concurrency is the global limit of prefetch jobs running at once (default 2).
Concurrency int
// QueueSize bounds queued jobs; more are dropped (default 128).
QueueSize int
// WarmInterval is how often in-progress resume points are warmed (default 15m).
WarmInterval time.Duration
// WarmBehind is pulled before the resume point, for the client's
// rewind-on-resume (default 4 MiB). The window after it is
// Cache.PrefetchBytes.
WarmBehind int64
// InProgressLimit is how many in-progress titles per user are warmed (default 20).
InProgressLimit int
// DoneTTL suppresses repeating a finished next-episode job (default 6h).
DoneTTL time.Duration
// RetryAfter suppresses retrying a failed job (default 30m).
RetryAfter time.Duration
// JobTimeout bounds one job (default 10m).
JobTimeout time.Duration
// PostPlayBytes is how much of the #1 post-play pick to pre-buffer
// (default 40 MiB, inside the 32–48 MiB the countdown needs).
PostPlayBytes int64
// Now is the clock (tests).
Now func() time.Time
}
Options tune the prefetcher. Zero values take the defaults noted.
type Prefetcher ¶
type Prefetcher struct {
// contains filtered or unexported fields
}
Prefetcher is the background prefetch worker pool.
func New ¶
New starts a Prefetcher with Options.Concurrency workers and the keep-warm loop. Call Close to stop it.
func (*Prefetcher) Close ¶
func (p *Prefetcher) Close() error
Close stops the workers; running jobs are cancelled.
func (*Prefetcher) OnTimeline ¶
func (p *Prefetcher) OnTimeline(user *core.User, key core.RatingKey, offset, duration time.Duration, state string)
OnTimeline is called by the Plex front end for every timeline update. It never blocks: past Cache.NextEpisodeAt of an episode it queues the next episode's prefetch (once per user and episode).
func (*Prefetcher) SetConfig ¶
func (p *Prefetcher) SetConfig(cfg config.Cache)
SetConfig applies a new cache config snapshot.
func (*Prefetcher) WarmNow ¶
func (p *Prefetcher) WarmNow()
WarmNow triggers a keep-warm pass without waiting for the interval.