use context to stop main() jobs
use
This commit is contained in:
@@ -325,13 +325,7 @@ func main() {
|
|||||||
|
|
||||||
defer logJob("scan watcher")()
|
defer logJob("scan watcher")()
|
||||||
|
|
||||||
done := make(chan struct{})
|
return scannr.ExecuteWatch(ctx)
|
||||||
errgrp.Go(func() error {
|
|
||||||
<-ctx.Done()
|
|
||||||
done <- struct{}{}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return scannr.ExecuteWatch(done)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
errgrp.Go(func() error {
|
errgrp.Go(func() error {
|
||||||
@@ -350,14 +344,7 @@ func main() {
|
|||||||
return fmt.Errorf("create tmp sock file: %w", err)
|
return fmt.Errorf("create tmp sock file: %w", err)
|
||||||
}
|
}
|
||||||
sockPath := filepath.Join(jukeboxTempDir, "sock")
|
sockPath := filepath.Join(jukeboxTempDir, "sock")
|
||||||
if err := jukebx.Start(sockPath, extraArgs); err != nil {
|
if err := jukebx.Start(ctx, sockPath, extraArgs); err != nil {
|
||||||
return fmt.Errorf("start jukebox: %w", err)
|
|
||||||
}
|
|
||||||
errgrp.Go(func() error {
|
|
||||||
<-ctx.Done()
|
|
||||||
return jukebx.Quit()
|
|
||||||
})
|
|
||||||
if err := jukebx.Wait(); err != nil {
|
|
||||||
return fmt.Errorf("start jukebox: %w", err)
|
return fmt.Errorf("start jukebox: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -25,7 +25,7 @@ require (
|
|||||||
github.com/sentriz/audiotags v0.0.0-20240202193907-618ae39d7743
|
github.com/sentriz/audiotags v0.0.0-20240202193907-618ae39d7743
|
||||||
github.com/sentriz/gormstore v0.0.0-20220105134332-64e31f7f6981
|
github.com/sentriz/gormstore v0.0.0-20220105134332-64e31f7f6981
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
go.senan.xyz/flagconf v0.1.4
|
go.senan.xyz/flagconf v0.1.5
|
||||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
||||||
golang.org/x/net v0.21.0
|
golang.org/x/net v0.21.0
|
||||||
golang.org/x/sync v0.6.0
|
golang.org/x/sync v0.6.0
|
||||||
@@ -59,7 +59,7 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
golang.org/x/crypto v0.19.0 // indirect
|
golang.org/x/crypto v0.20.0 // indirect
|
||||||
golang.org/x/image v0.15.0 // indirect
|
golang.org/x/image v0.15.0 // indirect
|
||||||
golang.org/x/sys v0.17.0 // indirect
|
golang.org/x/sys v0.17.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -137,15 +137,15 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.senan.xyz/flagconf v0.1.4 h1:j92ZqK4o299UBH2wVjhV6VevyhIHwrPSkzgj/+ShDCA=
|
go.senan.xyz/flagconf v0.1.5 h1:5HTNpA5jzH1XnsyR79pClXf9T+V+6OL/IsESORMrExs=
|
||||||
go.senan.xyz/flagconf v0.1.4/go.mod h1:CGD/sgYWiTacz1ojgsQRwErqLxtShWMpBxxnsJI6yaE=
|
go.senan.xyz/flagconf v0.1.5/go.mod h1:CGD/sgYWiTacz1ojgsQRwErqLxtShWMpBxxnsJI6yaE=
|
||||||
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
|
||||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package jukebox
|
package jukebox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -46,7 +47,7 @@ func New() *Jukebox {
|
|||||||
return &Jukebox{}
|
return &Jukebox{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Jukebox) Start(sockPath string, mpvExtraArgs []string) error {
|
func (j *Jukebox) Start(ctx context.Context, sockPath string, mpvExtraArgs []string) error {
|
||||||
const mpvName = "mpv"
|
const mpvName = "mpv"
|
||||||
if _, err := exec.LookPath(mpvName); err != nil {
|
if _, err := exec.LookPath(mpvName); err != nil {
|
||||||
return fmt.Errorf("look path: %w. did you forget to install it?", err)
|
return fmt.Errorf("look path: %w. did you forget to install it?", err)
|
||||||
@@ -56,7 +57,7 @@ func (j *Jukebox) Start(sockPath string, mpvExtraArgs []string) error {
|
|||||||
mpvArgs = append(mpvArgs, "--idle", "--no-config", "--no-video", MPVArg("--audio-display", "no"), MPVArg("--input-ipc-server", sockPath))
|
mpvArgs = append(mpvArgs, "--idle", "--no-config", "--no-video", MPVArg("--audio-display", "no"), MPVArg("--input-ipc-server", sockPath))
|
||||||
mpvArgs = append(mpvArgs, mpvExtraArgs...)
|
mpvArgs = append(mpvArgs, mpvExtraArgs...)
|
||||||
|
|
||||||
j.cmd = exec.Command(mpvName, mpvArgs...)
|
j.cmd = exec.CommandContext(ctx, mpvName, mpvArgs...)
|
||||||
if err := j.cmd.Start(); err != nil {
|
if err := j.cmd.Start(); err != nil {
|
||||||
return fmt.Errorf("start mpv process: %w", err)
|
return fmt.Errorf("start mpv process: %w", err)
|
||||||
}
|
}
|
||||||
@@ -87,14 +88,15 @@ func (j *Jukebox) Start(sockPath string, mpvExtraArgs []string) error {
|
|||||||
return fmt.Errorf("observe property: %w", err)
|
return fmt.Errorf("observe property: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *Jukebox) Wait() error {
|
|
||||||
var exitError *exec.ExitError
|
var exitError *exec.ExitError
|
||||||
if err := j.cmd.Wait(); err != nil && !errors.As(err, &exitError) {
|
if err := j.cmd.Wait(); err != nil && !errors.As(err, &exitError) {
|
||||||
return fmt.Errorf("wait jukebox: %w", err)
|
return fmt.Errorf("wait jukebox: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := j.conn.Close(); err != nil {
|
||||||
|
return fmt.Errorf("close: %w", err)
|
||||||
|
}
|
||||||
|
j.conn.WaitUntilClosed()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,26 +311,6 @@ func (j *Jukebox) GetStatus() (*Status, error) {
|
|||||||
return &status, nil
|
return &status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Jukebox) Quit() error {
|
|
||||||
defer lock(&j.mu)()
|
|
||||||
|
|
||||||
if j.conn == nil || j.conn.IsClosed() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
_, _ = j.conn.Call("quit")
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(250 * time.Millisecond)
|
|
||||||
_ = j.cmd.Process.Kill()
|
|
||||||
|
|
||||||
if err := j.conn.Close(); err != nil {
|
|
||||||
return fmt.Errorf("close: %w", err)
|
|
||||||
}
|
|
||||||
j.conn.WaitUntilClosed()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDecode(conn *mpvipc.Connection, dest any, property string) error {
|
func getDecode(conn *mpvipc.Connection, dest any, property string) error {
|
||||||
raw, err := conn.Get(property)
|
raw, err := conn.Get(property)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package jukebox_test
|
package jukebox_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -193,8 +194,11 @@ func newJukebox(tb testing.TB) *jukebox.Jukebox {
|
|||||||
|
|
||||||
sockPath := filepath.Join(tb.TempDir(), "mpv.sock")
|
sockPath := filepath.Join(tb.TempDir(), "mpv.sock")
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
j := jukebox.New()
|
j := jukebox.New()
|
||||||
err := j.Start(
|
err := j.Start(
|
||||||
|
ctx,
|
||||||
sockPath,
|
sockPath,
|
||||||
[]string{jukebox.MPVArg("--ao", "null")},
|
[]string{jukebox.MPVArg("--ao", "null")},
|
||||||
)
|
)
|
||||||
@@ -205,7 +209,7 @@ func newJukebox(tb testing.TB) *jukebox.Jukebox {
|
|||||||
tb.Fatalf("start jukebox: %v", err)
|
tb.Fatalf("start jukebox: %v", err)
|
||||||
}
|
}
|
||||||
tb.Cleanup(func() {
|
tb.Cleanup(func() {
|
||||||
j.Quit()
|
cancel()
|
||||||
})
|
})
|
||||||
return j
|
return j
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package scanner
|
package scanner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
@@ -111,7 +112,7 @@ func (s *Scanner) ScanAndClean(opts ScanOptions) (*State, error) {
|
|||||||
return st, errors.Join(st.errs...)
|
return st, errors.Join(st.errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) ExecuteWatch(done <-chan struct{}) error {
|
func (s *Scanner) ExecuteWatch(ctx context.Context) error {
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating watcher: %w", err)
|
return fmt.Errorf("creating watcher: %w", err)
|
||||||
@@ -180,7 +181,7 @@ func (s *Scanner) ExecuteWatch(done <-chan struct{}) error {
|
|||||||
case err := <-watcher.Errors:
|
case err := <-watcher.Errors:
|
||||||
log.Printf("error from watcher: %v\n", err)
|
log.Printf("error from watcher: %v\n", err)
|
||||||
|
|
||||||
case <-done:
|
case <-ctx.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user