blob: 4eb834d7533e9e51872b4f0db7baef75038a0f83 [file] [log] [blame]
package tasks
import (
"fmt"
)
type Status int
const (
StatusPending Status = 0
StatusRunning = 1
StatusFailed = 2
StatusDone = 3
)
type TaskDoneListener func(err error)
type Task interface {
Title() string
Start()
Status() Status
Err() error
Subtasks() []Task
AddSubtask(t Task) error
FinalizeSubtasks()
OnDone(l TaskDoneListener)
}
type basicTask struct {
title string
status Status
err error
subtasks []Task
done []bool
finalized bool
listeners []TaskDoneListener
}
func (b *basicTask) Title() string {
return b.title
}
func (b *basicTask) Status() Status {
return b.status
}
func (b *basicTask) Err() error {
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)
}
func (b *basicTask) callDoneListeners(err error) {
for _, l := range b.listeners {
go l(err)
}
if err == nil {
b.status = StatusDone
} else {
b.status = StatusFailed
b.err = err
}
}