mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-12 11:24:08 +00:00
fix(hls): snapshot state in Store and publish fully initialized runs
Address the completion review findings on top of the upstream review fixes: - Store runs on the engine's checkpoint goroutine without the task lock and serializes the returned value afterwards: take the fetcher mutex and return a deep copy instead of the live state pointer, matching the HTTP protocol's Store pattern - Load the journal and per-run base counters before publishing the run as active, so Stats/Progress never observe half-initialized fields - Bind the journal fingerprint to the key IV as well: a rotated IV on an otherwise identical plan would silently decrypt to garbage - Keep every EXT-X-MEDIA member per group instead of only the first one, so a group with a URI on a later member is still detected - After a merge that raced with a pause, keep the staged segments and exit silently instead of cleaning them up; drop a dead context check and an unused helper, and make the MAP identity and merge part-file names unambiguous
This commit is contained in:
1 parent
f1f17948c6
commit
f9410bbcc7
5 files changed
+79
-54
No files matched your search
@@ -59,12 +59,26 @@ func (fm *FetcherManager) DefaultConfig() any {
|
||||
|
||||
func (fm *FetcherManager) Store(f fetcher.Fetcher) (data any, err error) {
|
||||
_f := f.(*Fetcher)
|
||||
_f.mu.Lock()
|
||||
defer _f.mu.Unlock()
|
||||
if _f.state == nil {
|
||||
return nil, nil
|
||||
}
|
||||
// The segment plan is immutable after resolve; the completed-segment
|
||||
// journal lives on disk next to the segments.
|
||||
return _f.state, nil
|
||||
// The engine's periodic checkpoint calls Store without holding the task
|
||||
// lock and serializes the returned value afterwards, while Resolve/Patch/
|
||||
// Start mutate the live state under the fetcher mutex: return a snapshot
|
||||
// copy taken under that mutex, mirroring the HTTP protocol's Store.
|
||||
return cloneState(_f.state), nil
|
||||
}
|
||||
|
||||
func cloneState(state *fetcherState) *fetcherState {
|
||||
cloned := *state
|
||||
cloned.Segments = make([]*Segment, len(state.Segments))
|
||||
for i, seg := range state.Segments {
|
||||
s := *seg
|
||||
cloned.Segments[i] = &s
|
||||
}
|
||||
return &cloned
|
||||
}
|
||||
|
||||
func (fm *FetcherManager) Restore() (v any, f func(meta *fetcher.FetcherMeta, v any) fetcher.Fetcher) {
|
||||
|
||||
Reference in new issue
Block a user