From b40ecefd19d415ef0192a06504bc544a31f56a89 Mon Sep 17 00:00:00 2001 From: Erdem Toraman Date: Tue, 17 Dec 2019 09:44:16 +0200 Subject: [PATCH 1/3] added sql implementation --- wait/sql.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 wait/sql.go diff --git a/wait/sql.go b/wait/sql.go new file mode 100644 index 0000000000..dbfb95de8b --- /dev/null +++ b/wait/sql.go @@ -0,0 +1,63 @@ +package wait + +import ( + "context" + "database/sql" + "fmt" + "github.com/docker/go-connections/nat" + "time" +) + +func ForSQL(port nat.Port, driver string, url func(nat.Port) string) *waitForSql { + return &waitForSql{ + Port: port, + URL: url, + Driver: driver, + } +} + +type waitForSql struct { + URL func(port nat.Port) string + Driver string + Port nat.Port + startupTimeout time.Duration +} + +func (w *waitForSql) Timeout(duration time.Duration) *waitForSql { + w.startupTimeout = duration + return w +} + +func (w *waitForSql) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) { + if w.startupTimeout == 0 { + w.startupTimeout = time.Second*10 + } + ctx, cancel := context.WithTimeout(ctx, w.startupTimeout) + defer cancel() + + ticker := time.NewTicker(time.Millisecond * 100) + defer ticker.Stop() + + port, err := target.MappedPort(ctx, w.Port) + if err != nil { + return fmt.Errorf("target.MappedPort: %w", err) + } + + db, err := sql.Open(w.Driver, w.URL(port)) + if err != nil { + return fmt.Errorf("sql.Open: %w", err) + } + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-ticker.C: + + if _, err := db.ExecContext(ctx, "SELECT 1"); err != nil { + continue + } + return nil + } + } +} + From 119a93f6e9e3aad87ad00c1e7704dd75a39bf1e8 Mon Sep 17 00:00:00 2001 From: Erdem Toraman Date: Tue, 17 Dec 2019 09:58:01 +0200 Subject: [PATCH 2/3] added comments --- wait/sql.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/wait/sql.go b/wait/sql.go index dbfb95de8b..a9acbb4dc8 100644 --- a/wait/sql.go +++ b/wait/sql.go @@ -8,10 +8,11 @@ import ( "time" ) +//ForSQL constructs a new waitForSql strategy for the given driver func ForSQL(port nat.Port, driver string, url func(nat.Port) string) *waitForSql { return &waitForSql{ - Port: port, - URL: url, + Port: port, + URL: url, Driver: driver, } } @@ -23,14 +24,17 @@ type waitForSql struct { startupTimeout time.Duration } +//Timeout sets the maximum waiting time for the strategy after which it'll give up and return an error func (w *waitForSql) Timeout(duration time.Duration) *waitForSql { w.startupTimeout = duration return w } +//WaitUntilReady repeatedly tries to run "SELECT 1" query on the given port using sql and driver. +// If the it doesn't succeed until the timeout value which defaults to 10 seconds, it will return an error func (w *waitForSql) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) { if w.startupTimeout == 0 { - w.startupTimeout = time.Second*10 + w.startupTimeout = time.Second * 10 } ctx, cancel := context.WithTimeout(ctx, w.startupTimeout) defer cancel() @@ -60,4 +64,3 @@ func (w *waitForSql) WaitUntilReady(ctx context.Context, target StrategyTarget) } } } - From fdd39ffb4888b291aa2851ef9d953ddaf9ce6025 Mon Sep 17 00:00:00 2001 From: Erdem Toraman Date: Tue, 17 Dec 2019 10:07:19 +0200 Subject: [PATCH 3/3] use %v instead of %w to pass the build.. --- wait/sql.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wait/sql.go b/wait/sql.go index a9acbb4dc8..4498f8d0ea 100644 --- a/wait/sql.go +++ b/wait/sql.go @@ -44,12 +44,12 @@ func (w *waitForSql) WaitUntilReady(ctx context.Context, target StrategyTarget) port, err := target.MappedPort(ctx, w.Port) if err != nil { - return fmt.Errorf("target.MappedPort: %w", err) + return fmt.Errorf("target.MappedPort: %v", err) } db, err := sql.Open(w.Driver, w.URL(port)) if err != nil { - return fmt.Errorf("sql.Open: %w", err) + return fmt.Errorf("sql.Open: %v", err) } for { select {