diff --git a/README.md b/README.md index 961feb9..b9d5913 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,27 @@ But also this package can be donwloaded as utility and used from command line. # Library usage +## Simple ```GO import "github.com/antelman107/net-wait-go/wait" -if !wait.Do( - "tcp", // proto - []string{"postgres:5432"}, // addresses - time.Millisecond*100, // delay between requests - time.Second*15, // deadline - true, // debug -) { +if !wait.New().Do([]string{"postgres:5432"}) { + logger.Error("db is not available") + return +} +``` + +## All optional settings definition +```GO +import "github.com/antelman107/net-wait-go/wait" + +if !wait.New( + wait.WithProto("tcp"), + wait.WithWait(200*time.Millisecond), + wait.WithBreak(50*time.Millisecond), + wait.WithDeadline(15*time.Second), + wait.WithDebug(true), +).Do([]string{"postgres:5432"}) { logger.Error("db is not available") return } @@ -34,6 +45,8 @@ if !wait.Do( # Utility usage ```bash +net-wait-go + -addrs string address:port -deadline uint @@ -50,6 +63,8 @@ if !wait.Do( ```bash net-wait-go -addrs ya.ru:443 -debug true 2020/06/30 18:07:38 ya.ru:443 is OK + +return code is 0 ``` ## 2 addresses check @@ -57,6 +72,8 @@ net-wait-go -addrs ya.ru:443 -debug true net-wait-go -addrs ya.ru:443,yandex.ru:443 -debug true 2020/06/30 18:09:24 yandex.ru:443 is OK 2020/06/30 18:09:24 ya.ru:443 is OK + +return code is 0 ``` ## 2 addresses check fail @@ -65,6 +82,7 @@ net-wait-go -addrs ya.ru:445,yandex.ru:445 -debug true 2020/06/30 18:09:24 yandex.ru:443 is FAILED 2020/06/30 18:09:24 ya.ru:443 is is FAILED ... +return code is 1 ``` diff --git a/main.go b/main.go index 3289cce..d41d9f9 100644 --- a/main.go +++ b/main.go @@ -13,12 +13,19 @@ import ( func main() { var proto string flag.StringVar(&proto, "proto", "tcp", "tcp") + var addrs string flag.StringVar(&addrs, "addrs", "", "address:port") + var deadlineMS uint flag.UintVar(&deadlineMS, "deadline", 10000, "deadline in milliseconds") + var delayMS uint - flag.UintVar(&delayMS, "delay", 100, "delay in milliseconds") + flag.UintVar(&delayMS, "wait", 100, "delay of single request in milliseconds") + + var breakMS uint + flag.UintVar(&breakMS, "delay", 50, "break between requests in milliseconds") + var debug bool flag.BoolVar(&debug, "debug", false, "debug messages toggler") @@ -32,18 +39,18 @@ func main() { log.Println("addrs are not set") flag.Usage() - os.Exit(1) + os.Exit(2) } - if wait.Do( - proto, - addrsSlice, - time.Duration(delayMS)*time.Millisecond, - time.Duration(deadlineMS)*time.Millisecond, - debug, - ) { + if wait.New( + wait.WithProto("tcp"), + wait.WithWait(time.Duration(delayMS)*time.Millisecond), + wait.WithBreak(time.Duration(breakMS)*time.Millisecond), + wait.WithDeadline(time.Duration(deadlineMS)*time.Millisecond), + wait.WithDebug(debug), + ).Do(addrsSlice) { return } - os.Exit(2) + os.Exit(1) } diff --git a/wait/wait.go b/wait/wait.go index d1e5866..597cd28 100644 --- a/wait/wait.go +++ b/wait/wait.go @@ -7,8 +7,73 @@ import ( "time" ) -func Do(proto string, addrs []string, delay, deadline time.Duration, debug bool) bool { - deadlineCh := time.After(deadline) +type Executor struct { + Proto string + Addrs []string + Wait time.Duration + Break time.Duration + Deadline time.Duration + Debug bool +} + +type Option func(*Executor) + +func New(opts ...Option) *Executor { + const ( + defaultProto = "tcp" + defaultWait = 200 * time.Millisecond + defaultBreak = 50 * time.Millisecond + defaultDeadline = 15 * time.Second + defaultDebug = false + ) + + e := &Executor{ + Proto: defaultProto, + Wait: defaultWait, + Break: defaultBreak, + Deadline: defaultDeadline, + Debug: defaultDebug, + } + + for _, opt := range opts { + opt(e) + } + + return e +} + +func WithProto(proto string) Option { + return func(h *Executor) { + h.Proto = proto + } +} + +func WithWait(wait time.Duration) Option { + return func(h *Executor) { + h.Wait = wait + } +} + +func WithBreak(b time.Duration) Option { + return func(h *Executor) { + h.Break = b + } +} + +func WithDeadline(deadline time.Duration) Option { + return func(h *Executor) { + h.Deadline = deadline + } +} + +func WithDebug(debug bool) Option { + return func(h *Executor) { + h.Debug = debug + } +} + +func (e *Executor) Do(addrs []string) bool { + deadlineCh := time.After(e.Deadline) successCh := make(chan struct{}) wg := sync.WaitGroup{} @@ -20,18 +85,20 @@ func Do(proto string, addrs []string, delay, deadline time.Duration, debug bool) defer wg.Done() for { - conn, err := net.DialTimeout(proto, addr, delay) + conn, err := net.DialTimeout(e.Proto, addr, e.Wait) if err != nil { - if debug { + if e.Debug { log.Printf("%s is FAILED", addr) } - time.Sleep(delay) + if e.Break > 0 { + time.Sleep(e.Break) + } continue } - if debug { + if e.Debug { log.Printf("%s is OK", addr) } diff --git a/wait/wait_test.go b/wait/wait_test.go index 1273ceb..5ef37f4 100644 --- a/wait/wait_test.go +++ b/wait/wait_test.go @@ -3,7 +3,6 @@ package wait import ( "net" "testing" - "time" ) func getServer(addr string) net.Listener { @@ -31,11 +30,12 @@ func TestTCP(t *testing.T) { srv := getServer(ok) defer srv.Close() - if !Do("tcp", []string{ok}, time.Millisecond*100, time.Second, true) { + e := New(WithDebug(true)) + if !e.Do([]string{ok}) { t.FailNow() } - if Do("tcp", []string{notok}, time.Millisecond*100, time.Second, true) { + if e.Do([]string{notok}) { t.FailNow() } }