Documentation
¶
Overview ¶
Package holes is the shared model + threshold policy for "holes": runs of consecutive segments confirmed missing from Usenet providers. One table governs every moment the engine meets a hole:
- at IMPORT, the fast-fail sweep classifies a file's sampled damage (fail the import / import as degraded / keep checking),
- at HEALTH CHECK, sampled or full sweeps classify accumulated damage, and
- at PLAYBACK, the hole hooks decide per miss whether to zero-fill and keep streaming or to kill the stream and fail the file.
Ported from AIOStreams' holes.ts. This package is imported by usenet, importer, health and nzbfilesystem layers; it must stay dependency-free.
Index ¶
Constants ¶
const ( // MaxPadRunSegments is the longest run of consecutive missing segments // that may be zero-filled. A longer measured run fails the file. MaxPadRunSegments = 4 // MaxPadTotalSegments is the cumulative padded-segment cap per file. MaxPadTotalSegments = 64 // MaxPadFileBytesRatio is the cumulative padded-bytes share of the file // above which it is unwatchable. The segment-count caps are the primary // guards; this ratio only protects small files where the segment caps // would be a large share. MaxPadFileBytesRatio = 0.02 // ProjectionMinHits is the minimum number of confirmed misses a PARTIAL // sample needs before a projection may fail a file; an observed run // beyond MaxPadRunSegments fails regardless (measured, not projected). ProjectionMinHits = 8 // ProjectionMargin is how far a projection must exceed the cumulative cap // to fail early from partial evidence. ProjectionMargin = 2 )
Variables ¶
This section is empty.
Functions ¶
func EligibleFile ¶
EligibleFile reports whether a file may have missing segments zero-filled, based on its extension.
Types ¶
type Accumulator ¶
type Accumulator struct {
// contains filtered or unexported fields
}
Accumulator incrementally merges missing segments into maximal non-overlapping runs. Used by import/health sweeps (spread hits) and by playback sessions (pads as they happen, including out-of-order discovery via seeks). Not safe for concurrent use; callers hold their own lock.
func (*Accumulator) Add ¶
func (a *Accumulator) Add(index int)
Add records one missing segment, merging into adjacent runs.
func (*Accumulator) AddRun ¶
func (a *Accumulator) AddRun(run Run)
AddRun records a measured run, merging with any overlapping or adjacent existing runs.
func (*Accumulator) Has ¶
func (a *Accumulator) Has(index int) bool
Has reports whether the segment index lies inside a known run.
func (*Accumulator) Load ¶
func (a *Accumulator) Load(runs []Run)
Load seeds the accumulator from persisted runs.
func (*Accumulator) LongestRun ¶
func (a *Accumulator) LongestRun() int
LongestRun is the length of the longest run ever merged. It never shrinks.
func (*Accumulator) Runs ¶
func (a *Accumulator) Runs() []Run
Runs returns all runs ordered by Start. The slice is a copy.
func (*Accumulator) Total ¶
func (a *Accumulator) Total() int
Total is the total number of missing segments across all runs.
type Decision ¶
type Decision string
Decision is the playback hook's verdict for one confirmed missing segment.
type Impact ¶
type Impact struct {
Verdict Verdict `json:"verdict"`
// TotalMissing is the number of confirmed missing segments (capped
// captures may undercount; Verdict already accounts for that).
TotalMissing int `json:"total_missing"`
// LongestRun is the longest observed run of consecutive missing segments.
LongestRun int `json:"longest_run"`
// Sampled is how many segments the sweep checked (0 = playback discovery).
Sampled int `json:"sampled,omitempty"`
// TotalSegments is the file's full segment count.
TotalSegments int `json:"total_segments,omitempty"`
// PaddedRatio is missing bytes / file bytes, when the file size is known.
PaddedRatio float64 `json:"padded_ratio,omitempty"`
}
Impact is the serializable playback-impact summary persisted in health error details (playback_impact key) and rendered by the frontend.
type Run ¶
type Run struct {
// Start is the first missing segment index.
Start int
// Count is the number of consecutive missing segments.
Count int
}
Run is a run of consecutive missing segments in one file's segment space.
type Verdict ¶
type Verdict string
Verdict classifies a file's confirmed hole damage.
const ( // VerdictClean means no confirmed damage (only a FULL check can prove it). VerdictClean Verdict = "clean" // VerdictDegraded means damage within the padding caps: playable with // glitches, zero-filled during streaming. VerdictDegraded Verdict = "degraded" // VerdictFailed means damage beyond the caps: unwatchable. VerdictFailed Verdict = "failed" // VerdictUnknown means a partial sample found nothing — absence of // evidence, not evidence of absence. VerdictUnknown Verdict = "unknown" )
func Classify ¶
Classify applies the threshold table to a file's confirmed damage. runs must cover the file's whole segment space (i.e. come from a full check or the persisted hole map). fileBytes is the file's decoded size when known (<= 0 skips the ratio guard); avgSegBytes an average decoded segment size (encoded sizes are fine; yEnc overhead is negligible for the ratio guard).
func ClassifyProjected ¶
ClassifyProjected classifies from a partial, uniform sample. It never returns VerdictClean: absence of evidence is VerdictUnknown until a full check completes.