func Serve(ctx scope.Context, addr string) { http.Handle("/metrics", prometheus.Handler()) listener, err := net.Listen("tcp", addr) if err != nil { ctx.Terminate(err) } closed := false m := sync.Mutex{} closeListener := func() { m.Lock() if !closed { listener.Close() closed = true } m.Unlock() } // Spin off goroutine to watch ctx and close listener if shutdown requested. go func() { <-ctx.Done() closeListener() }() if err := http.Serve(listener, nil); err != nil { fmt.Printf("http[%s]: %s\n", addr, err) ctx.Terminate(err) } closeListener() ctx.WaitGroup().Done() }
func (ctrl *Controller) terminal(ctx scope.Context, ch ssh.Channel) { defer ch.Close() lines := make(chan string) term := terminal.NewTerminal(ch, "> ") go func() { for ctx.Err() == nil { line, err := term.ReadLine() if err != nil { ctx.Terminate(err) return } lines <- line } }() for { var line string select { case <-ctx.Done(): return case line = <-lines: } cmd := parse(line) fmt.Printf("[control] > %v\n", cmd) switch cmd[0] { case "": continue case "quit": return case "shutdown": ctrl.ctx.Terminate(fmt.Errorf("shutdown initiated from console")) default: runCommand(ctx.Fork(), ctrl, cmd[0], term, cmd[1:]) } } }
func ScanLoop(ctx scope.Context, c cluster.Cluster, pb *psql.Backend, interval time.Duration) { defer ctx.WaitGroup().Done() errCount := 0 for { t := time.After(interval) select { case <-ctx.Done(): return case <-t: if err := scan(ctx.Fork(), c, pb); err != nil { errCount++ fmt.Printf("scan error [%d/%d]: %s", errCount, maxErrors, err) if errCount > maxErrors { fmt.Printf("maximum scan errors exceeded, terminating\n") ctx.Terminate(fmt.Errorf("maximum scan errors exceeded")) return } continue } errCount = 0 } } }