-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathcleanup.go
More file actions
112 lines (104 loc) · 3.31 KB
/
Copy pathcleanup.go
File metadata and controls
112 lines (104 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package actions
import (
"context"
"fmt"
"log/slog"
"math"
"os"
"os/exec"
"path"
"github.com/tum-dev/gocast/runner/config"
"github.com/tum-dev/gocast/runner/pkg/metrics"
"github.com/tum-dev/gocast/runner/pkg/probe"
"github.com/tum-dev/gocast/runner/protobuf"
)
// Cleanup is an action that removes all contents in recordingDir if vodHealthy is true.
// otherwise, it uses the mv command, to move the broken live recording to {mass_dir}/broken.
func Cleanup(ctx context.Context, log *slog.Logger, _ chan *protobuf.Notification, d map[string]any, metrics *metrics.Broker) error {
recDir, ok := d["recordingDir"].(string)
if !ok {
return AbortingError(fmt.Errorf("no recordingDir in context"))
}
vodHealthy, ok := d["vodHealthy"].(bool)
if !ok {
return AbortingError(fmt.Errorf("no recordingDir in context"))
}
if vodHealthy {
err := os.RemoveAll(recDir)
if err != nil {
return AbortingError(fmt.Errorf("remove vod dir: %w", err))
}
return nil
}
// vod unhealthy, move to mass:
dst := path.Join(recDir, config.Config.StoragePath, "broken")
err := os.MkdirAll(dst, os.ModePerm)
if err != nil && !os.IsExist(err) {
return AbortingError(fmt.Errorf("create broken vod directory: %w", err))
}
log.Info("moving broken vod", "scr", recDir, "dst", dst)
cmd := exec.CommandContext(ctx, "mv", dst)
err = cmd.Start()
if err != nil {
return AbortingError(fmt.Errorf("start move broken recording command: %w", err))
}
err = cmd.Wait()
if err != nil {
return AbortingError(fmt.Errorf("wait move broken recording command: %w", err))
}
return nil
}
// ProbeVodHealth checks the duration of the live and vod playlists and sets d["vodHealthy"] to false if it detects
// a difference of the stream lengths of more than 10 seconds or if any of the probes fail or return no streams.
func ProbeVodHealth(ctx context.Context, log *slog.Logger, _ chan *protobuf.Notification, d map[string]any, metrics *metrics.Broker) error {
recDir, ok := d["recordingDir"].(string)
if !ok {
return AbortingError(fmt.Errorf("no recordingDir in context"))
}
vodDir, ok := d["vodDir"].(string)
if !ok {
return AbortingError(fmt.Errorf("no vodDir in context"))
}
probeLive, err := probe.Probe(ctx, path.Join(recDir, "playlist.m3u8"))
if err != nil {
log.Error("probe livestream", "err", err)
d["vodHealthy"] = false
return nil
}
probeVod, err := probe.Probe(ctx, path.Join(vodDir, "playlist.m3u8"))
if err != nil {
log.Error("probe vod", "err", err)
d["vodHealthy"] = false
return nil
}
if len(probeLive.Streams) == 0 {
log.Error("live streams # == 0")
d["vodHealthy"] = false
return nil
}
if len(probeVod.Streams) == 0 {
log.Error("vod streams # == 0")
d["vodHealthy"] = false
return nil
}
durationLive, err := probeLive.Streams[0].DurationFloat()
if err != nil {
log.Error("parse live stream duration", "err", err)
d["vodHealthy"] = false
return nil
}
durationVod, err := probeVod.Streams[0].DurationFloat()
if err != nil {
log.Error("parse vod stream duration", "err", err)
d["vodHealthy"] = false
return nil
}
if math.Max(durationVod, durationLive)-math.Min(durationVod, durationLive) > 10 {
log.Error("vod and live durations of by > 10s", "vodDuration", durationVod, "liveDuration", durationLive)
d["vodHealthy"] = false
return nil
}
log.Info("vod is healthy")
d["vodHealthy"] = true
return nil
}