Skip to content

Instantly share code, notes, and snippets.

@tonistiigi
Forked from alexellis/paint_status.go
Created September 16, 2017 00:39
Show Gist options
  • Save tonistiigi/b0c5a858f15e30615400e25fc04ba8fe to your computer and use it in GitHub Desktop.
Save tonistiigi/b0c5a858f15e30615400e25fc04ba8fe to your computer and use it in GitHub Desktop.
paint_status.go
package main
import (
"fmt"
"os/exec"
"strings"
"sync"
"github.com/morikuni/aec"
)
func main() {
statusMap = map[int]string{
Started: "started",
Stopped: "stopped",
}
maxWorkers := 1
workItems := []Work{
Work{Command: "sleep 1.1", Name: "Func 1"},
Work{Command: "sleep 0.1", Name: "Func 2"},
Work{Command: "sleep 0.1", Name: "Func 3"},
Work{Command: "sleep 1.1", Name: "Func 4"},
}
parallelRun(workItems, maxWorkers)
}
type Work struct {
Command string
Name string
Started time.Time
Finished *time.Time
}
type StatusUpdate struct {
Name string
Status int
}
const Started int = 0
const Stopped int = 1
var statusMap map[int]string
type ConsolePainter struct {
WorkMap *map[string]*Work
}
func (c *ConsolePainter) Paint() {
numLines := 0
done := 0
for range *c.WorkMap {
numLines++
}
upN := aec.Up(uint(numLines + 1))
fmt.Print(upN)
for _, v := range *c.WorkMap {
var line string
if v.Finished == nil {
line = fmt.Sprintf("[%-40s] - %-40s", v.Name, "running")
} else {
line = fmt.Sprintf("[%-40s] - %-40s", v.Name, "done")
done++
}
fmt.Printf("%-100s\n", line)
}
fmt.Printf("Done: %d/%d \n", done, numLines)
}
func parallelRun(workItems []Work, maxWorkers int) {
wg := sync.WaitGroup{}
painter := ConsolePainter{}
workMap := make(map[string]*Work)
for _, item := range workItems {
copied := item
workMap[item.Name] = &copied
}
painter.WorkMap = &workMap
workChannel := make(chan Work)
statusUpdate := make(chan StatusUpdate)
for i := 0; i < maxWorkers; i++ {
wg.Add(1)
go func(index int) {
for work := range workChannel {
statusUpdate <- StatusUpdate{Name: work.Name, Status: Started}
workParts := strings.Split(work.Command, " ")
targetCmd := exec.Command(workParts[0], workParts[1:]...)
out, _ := targetCmd.CombinedOutput()
strings.Contains(string(out), "")
statusUpdate <- StatusUpdate{Name: work.Name, Status: Stopped}
}
wg.Done()
}(i)
}
statusDone := make(chan struct{})
go func() {
defer close(statusDone)
for update := range statusUpdate {
mapItem := workMap[update.Name]
if mapItem != nil {
if update.Status == Started {
mapItem.Started = time.Now()
} else if update.Status == Stopped {
var finished time.Time
finished = time.Now()
mapItem.Finished = &finished
}
painter.Paint()
}
}
}()
for i := 0; i < len(workItems); i++ {
workChannel <- workItems[i]
}
close(workChannel)
wg.Wait()
close(statusUpdate)
<-statusDone
// painter.Paint()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment