Skip to content

Instantly share code, notes, and snippets.

@ma6174
Created June 11, 2017 01:49
Show Gist options
  • Save ma6174/7d2aecb2dead822c7d157e616c55c61c to your computer and use it in GitHub Desktop.
Save ma6174/7d2aecb2dead822c7d157e616c55c61c to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"log"
"math/rand"
"time"
)
type Hosts struct {
hosts []string
}
func (h *Hosts) Get() (host string) {
if h.Len() == 0 {
panic("no hosts")
}
id := rand.Intn(h.Len())
var h2 []string
h2 = append(h2, h.hosts[:id]...)
h2 = append(h2, h.hosts[id+1:]...)
h.hosts, host = h2, h.hosts[id]
return
}
func (h *Hosts) Len() int {
return len(h.hosts)
}
type Job func(host string) error
func LbWnDo(hosts []string, w int, job Job) (err error) {
if len(hosts) < w {
err = errors.New("no enough ok count")
return
}
var h *Hosts = &Hosts{hosts}
var okCount, doingCount int
var errCh = make(chan error, len(hosts))
for okCount != w {
if doingCount < w-okCount && h.Len() > 0 {
host := h.Get()
go func(host string) { errCh <- job(host) }(host)
doingCount++
continue
}
if doingCount == 0 {
break
}
log.Println("doing", doingCount)
err = <-errCh
doingCount--
if err != nil {
log.Println(err)
continue
}
okCount++
log.Println("OK", okCount)
}
if okCount != w {
log.Println("okCount:", okCount)
err = errors.New("no enough ok count")
}
return
}
var job = func(host string) error {
r := rand.Intn(10) + 1
log.Println("do with host", host, r)
time.Sleep(time.Duration(r*100) * time.Millisecond)
if r%3 != 0 {
return errors.New("host " + host + " err")
}
log.Println(host, "ok")
return nil
}
func main() {
log.SetFlags(log.LstdFlags | log.Lmicroseconds)
var hosts = []string{"a", "b", "c", "d", "e"}
rand.Seed(time.Now().UnixNano())
log.Println(LbWnDo(hosts, 2, job))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment