From d25b31e4c8ba0c3116749a03e1f28cad1df5ff45 Mon Sep 17 00:00:00 2001 From: Daniel Hess Date: Sun, 11 Apr 2021 16:13:03 -0700 Subject: [PATCH 1/2] add callback blocker for general use --- cbblocker/cbblocker.go | 38 ++++++++++++++++++++++++++++++++++ cbblocker/dbblocker_test.go | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 cbblocker/cbblocker.go create mode 100644 cbblocker/dbblocker_test.go diff --git a/cbblocker/cbblocker.go b/cbblocker/cbblocker.go new file mode 100644 index 0000000..d7025e3 --- /dev/null +++ b/cbblocker/cbblocker.go @@ -0,0 +1,38 @@ +package cbblocker + +import ( + "time" +) + +type Blocker struct { + callback func() error + duration time.Duration +} + +func New(callback func() error, poll time.Duration) *Blocker { + return &Blocker{ + callback: callback, + duration: poll, + } +} + +func (g *Blocker) Blockit() <-chan bool { + pass := make(chan bool) + + go func() { + for { + err := g.callback() + if err != nil { + <-time.After(g.duration) + continue + } + + pass <- true + close(pass) + + break + } + }() + + return pass +} diff --git a/cbblocker/dbblocker_test.go b/cbblocker/dbblocker_test.go new file mode 100644 index 0000000..658a203 --- /dev/null +++ b/cbblocker/dbblocker_test.go @@ -0,0 +1,41 @@ +package cbblocker_test + +import ( + "fmt" + "testing" + "time" + + "github.com/gomicro/blockit/cbblocker" + + "github.com/franela/goblin" + . "github.com/onsi/gomega" +) + +func TestCallbackBlockers(t *testing.T) { + g := goblin.Goblin(t) + RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) }) + + g.Describe("Callback Blocking", func() { + g.It("should block until callback returns no error", func() { + ep := eventualPass{} + + b := cbblocker.New(ep.do, 10*time.Millisecond) + Eventually(<-b.Blockit()).Should(BeTrue()) + Expect(ep.Fails).To(Equal(4)) + }) + }) +} + +type eventualPass struct { + Fails int +} + +func (ep *eventualPass) do() error { + if ep.Fails > 3 { + return nil + } + + ep.Fails++ + + return fmt.Errorf("didn't pass") +} From f44b1a92d194f96750a2a2f48d68a026f1f13595 Mon Sep 17 00:00:00 2001 From: Daniel Hess Date: Sun, 11 Apr 2021 16:13:16 -0700 Subject: [PATCH 2/2] reduce the dbblocker to use the callback blocker --- dbblocker/dbblocker.go | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/dbblocker/dbblocker.go b/dbblocker/dbblocker.go index 20607d4..0e7731d 100644 --- a/dbblocker/dbblocker.go +++ b/dbblocker/dbblocker.go @@ -3,38 +3,11 @@ package dbblocker import ( "database/sql" "time" -) -// Blocker represents a SQL database connection to monitor for connectivity -// and block until a connection is established. -type Blocker struct { - db *sql.DB -} + "github.com/gomicro/blockit/cbblocker" +) // New takes a SQL database object and returns a newly instantiated Blocker -func New(db *sql.DB) *Blocker { - return &Blocker{db: db} -} - -// Blockit meets the blocker interface. It returns a read only channel that will -// receive true when the database is connected. -func (d *Blocker) Blockit() <-chan bool { - connected := make(chan bool) - - go func() { - for { - err := d.db.Ping() - if err != nil { - <-time.After(1 * time.Second) - continue - } - - connected <- true - close(connected) - - break - } - }() - - return connected +func New(db *sql.DB) *cbblocker.Blocker { + return cbblocker.New(db.Ping, 1*time.Second) }