summaryrefslogtreecommitdiff
path: root/recording/task.go
diff options
context:
space:
mode:
Diffstat (limited to 'recording/task.go')
-rw-r--r--recording/task.go87
1 files changed, 87 insertions, 0 deletions
diff --git a/recording/task.go b/recording/task.go
new file mode 100644
index 0000000..9aa41a8
--- /dev/null
+++ b/recording/task.go
@@ -0,0 +1,87 @@
+package recording
+
+/*
+In this file we implement task lifecycle management.
+Concrete task works are done in the `runner.go` file.
+*/
+
+import (
+ "bilibili-livestream-archiver/logging"
+ "context"
+ "fmt"
+)
+
+type TaskStatus int
+
+const (
+ StNotStarted TaskStatus = iota
+ StRunning
+ StRestarting
+ StStopped
+)
+
+var (
+ ErrTaskIsAlreadyStarted = fmt.Errorf("task is already started")
+ ErrTaskIsStopped = fmt.Errorf("restarting a stopped task is not allowed")
+)
+
+// RunningTask is an augmented TaskConfig struct
+// that contains volatile runtime information.
+type RunningTask struct {
+ TaskConfig
+ // ctx: the biggest context this task uses. It may create children contexts.
+ ctx context.Context
+ // result: if the task is ended, here is the returned error
+ result error
+ // status: running status
+ status TaskStatus
+ // hookStarted: called asynchronously when the task is started. This won't be called when restarting.
+ hookStarted func()
+ // hookStopped: called asynchronously when the task is stopped. This won't be called when restarting.
+ hookStopped func()
+ // logger: where to print logs
+ logger logging.Logger
+}
+
+func NewRunningTask(
+ config TaskConfig,
+ ctx context.Context,
+ hookStarted func(),
+ hookStopped func(),
+ logger logging.Logger,
+) RunningTask {
+ return RunningTask{
+ TaskConfig: config,
+ ctx: ctx,
+ status: StNotStarted,
+ hookStarted: hookStarted,
+ hookStopped: hookStopped,
+ logger: logger,
+ }
+}
+
+func (t *RunningTask) StartTask() error {
+ st := t.status
+ switch st {
+ case StNotStarted:
+ // TODO real start
+ go func() {
+ defer func() { t.status = StStopped }()
+ t.hookStarted()
+ defer t.hookStopped()
+ // do the task
+ _ = t.runTaskWithAutoRestart()
+ }()
+ return nil
+ case StRunning:
+ return ErrTaskIsAlreadyStarted
+ case StRestarting:
+ return ErrTaskIsAlreadyStarted
+ case StStopped:
+ // we don't allow starting a stopped task
+ // because some state needs to be reset
+ // just create a new task and run
+ return ErrTaskIsStopped
+ }
+ panic(fmt.Errorf("invalid task status: %v", st))
+}