From 68538e93a26f15bd1795ae89a322672b6a3670a0 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Tue, 9 Apr 2019 08:56:05 +0200 Subject: [PATCH] Make db connect faster (remove initial delay) and more robust --- internal/db/connector.go | 74 +++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/internal/db/connector.go b/internal/db/connector.go index a4b75022e..a7a796104 100644 --- a/internal/db/connector.go +++ b/internal/db/connector.go @@ -9,28 +9,72 @@ import ( "github.com/titpetric/factory" ) +const ( + maxTries = 100 + delay = 5 * time.Second + timeout = 1 * time.Minute +) + func TryToConnect(ctx context.Context, name, dsn, profiler string) (db *factory.DB, err error) { factory.Database.Add(name, dsn) - var try = 0 - timeout := time.After(time.Minute) - delay := 5 * time.Second + var ( + connErrCh = make(chan error, 1) + ) - for { - select { - case <-ctx.Done(): - return nil, errors.New("cancelled") - case <-timeout: - return nil, errors.New("connection timeout") - case <-time.After(delay): + defer close(connErrCh) + + log.Printf("Connecting to the DB (%q, %q)", name, dsn) + + go func() { + var ( + try = 0 + ) + + for { try++ + + if maxTries <= try { + err = errors.Errorf("could not connect to %q, in %d tries", name, try) + return + } + db, err = factory.Database.Get(name) if err != nil { - log.Printf("Failed to connect, try %d, error: %v, retry in %.0fs", try, err, delay.Seconds()) - continue + log.Printf( + "could not connect to %q, try %d, error: %v, retry in %.0fs", + name, + try, + err, + delay.Seconds(), + ) + + select { + case <-ctx.Done(): + // Forced break + break + case <-time.After(delay): + // Wait before next try + continue + } } + + // Connected + break + } + + connErrCh <- err + }() + + select { + case err = <-connErrCh: break + case <-time.After(timeout): + // Wait before next try + return nil, errors.Errorf("db init for %q timedout", name) + case <-ctx.Done(): + return nil, errors.Errorf("db connection for %q cancelled", name) } // @todo: profiling as an external service? @@ -41,5 +85,9 @@ func TryToConnect(ctx context.Context, name, dsn, profiler string) (db *factory. log.Println("No database query profiler selected") } - return + if err != nil { + return nil, err + } + + return db, nil }