fix: cancel in-flight encode on SIGINT/SIGTERM via context plumbing
Thread context.Context from main through watcher, encoder, and metadata clients so a Ctrl-C during a multi-hour encode immediately kills the ffmpeg/ffprobe/opusenc children instead of waiting for them to finish. - main: signal.NotifyContext replaces the manual sigChan + done goroutine - watcher.Start: takes ctx, exits on ctx.Done(); processFn signature is now func(context.Context, string) error - encoder: Transcode and every helper (extractAudio, encodeOpus, encodeVideo, GetMediaInfo, GetStreamLanguages, calculateZscaleWidth) take ctx; every exec.Command becomes exec.CommandContext so the child is SIGKILL'd on cancel - metadata: FetchMovieMetadata, FetchSeriesMetadata, fetchTVMazeJSON take ctx and use http.NewRequestWithContext Mover stays ctx-free intentionally: a rename is fast enough that mid-cancel cleanup is the next-restart's problem. processFile's deferred RemoveAll(workDir) and failToFailed still run after cancel, so partial output dies in the work dir and the source moves to failed/.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -109,10 +110,14 @@ func ParseMediaType(filename string) types.MediaType {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *Client) FetchMovieMetadata(imdbID string) (*types.Metadata, error) {
|
||||
func (c *Client) FetchMovieMetadata(ctx context.Context, imdbID string) (*types.Metadata, error) {
|
||||
url := fmt.Sprintf("%s?i=%s&apikey=%s", omdbAPIURL, imdbID, c.omdbAPIKey)
|
||||
|
||||
resp, err := c.httpClient.Get(url)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("building OMDb request: %w", err)
|
||||
}
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching OMDb: %w", err)
|
||||
}
|
||||
@@ -153,7 +158,7 @@ func (c *Client) FetchMovieMetadata(imdbID string) (*types.Metadata, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) FetchSeriesMetadata(tvmazeID, season, episode string) (*types.Metadata, error) {
|
||||
func (c *Client) FetchSeriesMetadata(ctx context.Context, tvmazeID, season, episode string) (*types.Metadata, error) {
|
||||
seasonNum, err := strconv.Atoi(season)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing season %q: %w", season, err)
|
||||
@@ -165,13 +170,13 @@ func (c *Client) FetchSeriesMetadata(tvmazeID, season, episode string) (*types.M
|
||||
|
||||
epURL := fmt.Sprintf("%s/shows/%s/episodebynumber?season=%d&number=%d", tvmazeAPIURL, tvmazeID, seasonNum, episodeNum)
|
||||
var ep TVMazeEpisode
|
||||
if err := c.fetchTVMazeJSON(epURL, &ep); err != nil {
|
||||
if err := c.fetchTVMazeJSON(ctx, epURL, &ep); err != nil {
|
||||
return nil, fmt.Errorf("TVmaze episode %s S%dE%d: %w", tvmazeID, seasonNum, episodeNum, err)
|
||||
}
|
||||
|
||||
showURL := fmt.Sprintf("%s/shows/%s", tvmazeAPIURL, tvmazeID)
|
||||
var show TVMazeShowResponse
|
||||
if err := c.fetchTVMazeJSON(showURL, &show); err != nil {
|
||||
if err := c.fetchTVMazeJSON(ctx, showURL, &show); err != nil {
|
||||
return nil, fmt.Errorf("TVmaze show %s: %w", tvmazeID, err)
|
||||
}
|
||||
|
||||
@@ -192,8 +197,12 @@ func (c *Client) FetchSeriesMetadata(tvmazeID, season, episode string) (*types.M
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) fetchTVMazeJSON(url string, v interface{}) error {
|
||||
resp, err := c.httpClient.Get(url)
|
||||
func (c *Client) fetchTVMazeJSON(ctx context.Context, url string, v interface{}) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build request: %w", err)
|
||||
}
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GET: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user