First pass at full fork pretty much complete.
This commit is contained in:
@@ -34,6 +34,8 @@ const (
|
||||
|
||||
var Directory string
|
||||
|
||||
var activeRecordings sync.Map
|
||||
|
||||
type Client struct {
|
||||
hall *hall.Hall
|
||||
id string
|
||||
@@ -250,6 +252,7 @@ func newRecorder(client *Client, directory string) (*recorder, error) {
|
||||
done: make(chan error, 1),
|
||||
sources: make(map[*diskTrack]chan []byte),
|
||||
}
|
||||
activeRecordings.Store(path, struct{}{})
|
||||
go r.mix()
|
||||
return r, nil
|
||||
}
|
||||
@@ -358,6 +361,7 @@ func (r *recorder) Close() error {
|
||||
err := <-r.done
|
||||
stdinErr := r.stdin.Close()
|
||||
waitErr := r.cmd.Wait()
|
||||
activeRecordings.Delete(r.path)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -368,6 +372,10 @@ func (r *recorder) Close() error {
|
||||
if waitErr != nil {
|
||||
return waitErr
|
||||
}
|
||||
now := time.Now()
|
||||
if err := os.Chtimes(r.path, now, now); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -658,6 +666,49 @@ func openDiskFile(directory, extension string) (*os.File, error) {
|
||||
return nil, errors.New("couldn't create file")
|
||||
}
|
||||
|
||||
func CleanupOldRecordings(retention time.Duration) error {
|
||||
if retention <= 0 {
|
||||
return nil
|
||||
}
|
||||
cutoff := time.Now().Add(-retention)
|
||||
err := filepath.WalkDir(
|
||||
Directory,
|
||||
func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
log.Printf("Recording cleanup %v: %v", path, err)
|
||||
return nil
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
name := d.Name()
|
||||
if !strings.HasPrefix(name, "skald-recording-") ||
|
||||
filepath.Ext(name) != ".ogg" {
|
||||
return nil
|
||||
}
|
||||
if _, ok := activeRecordings.Load(path); ok {
|
||||
return nil
|
||||
}
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
log.Printf("Recording cleanup %v: %v", path, err)
|
||||
return nil
|
||||
}
|
||||
if info.ModTime().After(cutoff) {
|
||||
return nil
|
||||
}
|
||||
if err := os.Remove(path); err != nil {
|
||||
log.Printf("Recording cleanup %v: %v", path, err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func drainStderr(prefix string, r io.Reader) {
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
|
||||
@@ -46,6 +46,63 @@ func TestOpenDiskFileUsesSkaldOggName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupOldRecordings(t *testing.T) {
|
||||
oldDirectory := Directory
|
||||
defer func() {
|
||||
Directory = oldDirectory
|
||||
}()
|
||||
|
||||
Directory = t.TempDir()
|
||||
hallDir := filepath.Join(Directory, "test")
|
||||
if err := os.MkdirAll(hallDir, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
oldRecording := filepath.Join(hallDir, "skald-recording-20000101-000000.ogg")
|
||||
activeRecording := filepath.Join(hallDir, "skald-recording-20000101-010000.ogg")
|
||||
newRecording := filepath.Join(hallDir, "skald-recording-29990101-000000.ogg")
|
||||
otherFile := filepath.Join(hallDir, "notes.txt")
|
||||
for _, name := range []string{oldRecording, activeRecording, newRecording, otherFile} {
|
||||
if err := os.WriteFile(name, []byte("test"), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
oldTime := time.Now().Add(-48 * time.Hour)
|
||||
newTime := time.Now()
|
||||
if err := os.Chtimes(oldRecording, oldTime, oldTime); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Chtimes(activeRecording, oldTime, oldTime); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Chtimes(newRecording, newTime, newTime); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Chtimes(otherFile, oldTime, oldTime); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
activeRecordings.Store(activeRecording, struct{}{})
|
||||
defer activeRecordings.Delete(activeRecording)
|
||||
|
||||
if err := CleanupOldRecordings(24 * time.Hour); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := os.Stat(oldRecording); !os.IsNotExist(err) {
|
||||
t.Fatalf("old recording still exists or stat failed unexpectedly: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(newRecording); err != nil {
|
||||
t.Fatalf("new recording was removed: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(activeRecording); err != nil {
|
||||
t.Fatalf("active recording was removed: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(otherFile); err != nil {
|
||||
t.Fatalf("non-recording file was removed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMixFrameClipsAndSumsSources(t *testing.T) {
|
||||
a := make(chan []byte, 1)
|
||||
b := make(chan []byte, 1)
|
||||
|
||||
Reference in New Issue
Block a user