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:
+12
-17
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
@@ -61,24 +62,18 @@ func main() {
|
||||
|
||||
metaClient := metadata.NewClient(cfg.OMDBAPIKey)
|
||||
|
||||
done := make(chan struct{})
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
<-sigChan
|
||||
close(done)
|
||||
}()
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
defer cancel()
|
||||
|
||||
w := watcher.New(cfg.Paths.Input, 15)
|
||||
w.Start(func(inputPath string) error {
|
||||
return processFile(inputPath, cfg, enc, metaClient, log)
|
||||
}, done)
|
||||
w.Start(ctx, func(ctx context.Context, inputPath string) error {
|
||||
return processFile(ctx, inputPath, cfg, enc, metaClient, log)
|
||||
})
|
||||
|
||||
log.Info("videnc-vibe started")
|
||||
}
|
||||
|
||||
func processFile(inputPath string, cfg *types.Config, enc *encoder.Encoder, metaClient *metadata.Client, log *logger.Logger) error {
|
||||
func processFile(ctx context.Context, inputPath string, cfg *types.Config, enc *encoder.Encoder, metaClient *metadata.Client, log *logger.Logger) error {
|
||||
log.Info(fmt.Sprintf("Processing: %s", inputPath))
|
||||
|
||||
filename := filepath.Base(inputPath)
|
||||
@@ -97,14 +92,14 @@ func processFile(inputPath string, cfg *types.Config, enc *encoder.Encoder, meta
|
||||
// Cleanup the work directory on every exit path, success or failure.
|
||||
defer os.RemoveAll(workDir)
|
||||
|
||||
width, height, interlaced, err := enc.GetMediaInfo(inputPath)
|
||||
width, height, interlaced, err := enc.GetMediaInfo(ctx, inputPath)
|
||||
if err != nil {
|
||||
log.ErrorFile(inputPath, "Getting media info", err.Error())
|
||||
failToFailed(inputPath, cfg.Paths.Failed, log)
|
||||
return err
|
||||
}
|
||||
|
||||
streamLangs, err := enc.GetStreamLanguages(inputPath)
|
||||
streamLangs, err := enc.GetStreamLanguages(ctx, inputPath)
|
||||
if err != nil {
|
||||
log.ErrorFile(inputPath, "Getting stream languages", err.Error())
|
||||
}
|
||||
@@ -130,12 +125,12 @@ func processFile(inputPath string, cfg *types.Config, enc *encoder.Encoder, meta
|
||||
|
||||
var meta *types.Metadata
|
||||
if isSeries && tvmazeID != "" && season != "" && episode != "" {
|
||||
meta, err = metaClient.FetchSeriesMetadata(tvmazeID, season, episode)
|
||||
meta, err = metaClient.FetchSeriesMetadata(ctx, tvmazeID, season, episode)
|
||||
if err != nil {
|
||||
log.ErrorFile(inputPath, "Fetching series metadata", err.Error())
|
||||
}
|
||||
} else if imdbID != "" {
|
||||
meta, err = metaClient.FetchMovieMetadata(imdbID)
|
||||
meta, err = metaClient.FetchMovieMetadata(ctx, imdbID)
|
||||
if err != nil {
|
||||
log.ErrorFile(inputPath, "Fetching movie metadata", err.Error())
|
||||
}
|
||||
@@ -159,7 +154,7 @@ func processFile(inputPath string, cfg *types.Config, enc *encoder.Encoder, meta
|
||||
DeleteOrigin: deleteOrigin,
|
||||
}
|
||||
|
||||
if err := enc.Transcode(inputPath, workDir, job, meta, interlaced, streamLangs); err != nil {
|
||||
if err := enc.Transcode(ctx, inputPath, workDir, job, meta, interlaced, streamLangs); err != nil {
|
||||
log.ErrorFile(inputPath, "Transcoding", err.Error())
|
||||
failToFailed(inputPath, cfg.Paths.Failed, log)
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user