schnutibox/vendor/go.xsfx.dev/don/don.go

61 lines
1.2 KiB
Go

// Package don is a little helper if you need to check for the readiness of something.
// This could be a command to run (like ssh) or a `db.Ping()` for check of the readiness
// of a database container.
package don
import (
"errors"
"os"
"os/exec"
"time"
"github.com/rs/zerolog/log"
)
var errTimeout = errors.New("timeout")
// Cmd returns a `func() bool` for working with don.Check. It executes a command and
// returns a true if everything looks fine or a false if there was some kind of error.
func Cmd(c string) func() bool {
return func() bool {
cmd := exec.Command("sh", "-c", c)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Warn().Err(err).Msg("cmd has error")
return false
}
return true
}
}
// Check takes a function that executes something and returns a bool to indicate if
// something is ready or not. It returns an error if it timeouts.
func Check(f func() bool, timeout time.Duration, retry time.Duration) error {
chReady := make(chan struct{})
go func() {
for {
if f() {
chReady <- struct{}{}
return
}
<-time.After(retry)
log.Info().Msg("retrying")
}
}()
select {
case <-chReady:
return nil
case <-time.After(timeout):
return errTimeout
}
}