installer: helper leaf/parent tasks
diff --git a/core/installer/tasks/tasks.go b/core/installer/tasks/tasks.go
index 4eb834d..9b0d533 100644
--- a/core/installer/tasks/tasks.go
+++ b/core/installer/tasks/tasks.go
@@ -1,9 +1,5 @@
package tasks
-import (
- "fmt"
-)
-
type Status int
const (
@@ -21,8 +17,6 @@
Status() Status
Err() error
Subtasks() []Task
- AddSubtask(t Task) error
- FinalizeSubtasks()
OnDone(l TaskDoneListener)
}
@@ -30,12 +24,18 @@
title string
status Status
err error
- subtasks []Task
- done []bool
- finalized bool
listeners []TaskDoneListener
}
+func newBasicTask(title string) basicTask {
+ return basicTask{
+ title: title,
+ status: StatusPending,
+ err: nil,
+ listeners: make([]TaskDoneListener, 0),
+ }
+}
+
func (b *basicTask) Title() string {
return b.title
}
@@ -48,47 +48,6 @@
return b.err
}
-func (b *basicTask) Subtasks() []Task {
- return b.subtasks
-}
-
-func (b *basicTask) AddSubtask(t Task) error {
- if b.finalized {
- return fmt.Errorf("already finalized")
- }
- i := len(b.subtasks)
- b.subtasks = append(b.subtasks, t)
- b.done = append(b.done, false)
- t.OnDone(func(err error) {
- if b.done[i] {
- panic(fmt.Sprintf("already done: %s", b.subtasks[i].Title()))
- }
- b.done[i] = true
- if err != nil {
- b.callDoneListeners(err)
- }
- if !b.finalized {
- return
- }
- done := 0
- for _, d := range b.done {
- if d {
- done++
- } else {
- break
- }
- }
- if done == len(b.subtasks) {
- b.callDoneListeners(nil)
- }
- })
- return nil
-}
-
-func (b *basicTask) FinalizeSubtasks() {
- b.finalized = true
-}
-
func (b *basicTask) OnDone(l TaskDoneListener) {
b.listeners = append(b.listeners, l)
}
@@ -104,3 +63,68 @@
b.err = err
}
}
+
+type leafTask struct {
+ basicTask
+ start func() error
+}
+
+func newLeafTask(title string, start func() error) leafTask {
+ return leafTask{
+ basicTask: newBasicTask(title),
+ start: start,
+ }
+}
+
+func (b *leafTask) Subtasks() []Task {
+ return make([]Task, 0)
+}
+
+func (b *leafTask) Start() {
+ b.callDoneListeners(b.start())
+}
+
+type parentTask struct {
+ leafTask
+ subtasks []Task
+}
+
+func newParentTask(title string, start func() error, subtasks ...Task) parentTask {
+ return parentTask{
+ leafTask: newLeafTask(title, start),
+ subtasks: subtasks,
+ }
+}
+
+func (t *parentTask) Subtasks() []Task {
+ return t.subtasks
+}
+
+type sequentialParentTask struct {
+ parentTask
+}
+
+func newSequentialParentTask(title string, subtasks ...Task) sequentialParentTask {
+ start := func() error {
+ errCh := make(chan error)
+ for i := range subtasks[:len(subtasks)-1] {
+ next := i + 1
+ subtasks[i].OnDone(func(err error) {
+ if err == nil {
+ go subtasks[next].Start()
+ } else {
+ errCh <- err
+ }
+ })
+ }
+ subtasks[len(subtasks)-1].OnDone(func(err error) {
+ errCh <- err
+ })
+ go subtasks[0].Start()
+ return <-errCh
+ }
+ t := sequentialParentTask{
+ parentTask: newParentTask(title, start, subtasks...),
+ }
+ return t
+}