helper/slowmessage

This commit is contained in:
Mitchell Hashimoto 2017-02-14 09:27:23 -08:00
parent a7cfb8062b
commit 2124135287
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,34 @@
package slowmessage
import (
"time"
)
// SlowFunc is the function that could be slow. Usually, you'll have to
// wrap an existing function in a lambda to make it match this type signature.
type SlowFunc func() error
// CallbackFunc is the function that is triggered when the threshold is reached.
type CallbackFunc func()
// Do calls sf. If threshold time has passed, cb is called. Note that this
// call will be made concurrently to sf still running.
func Do(threshold time.Duration, sf SlowFunc, cb CallbackFunc) error {
// Call the slow function
errCh := make(chan error, 1)
go func() {
errCh <- sf()
}()
// Wait for it to complete or the threshold to pass
select {
case err := <-errCh:
return err
case <-time.After(threshold):
// Threshold reached, call the callback
cb()
}
// Wait an indefinite amount of time for it to finally complete
return <-errCh
}

View File

@ -0,0 +1,82 @@
package slowmessage
import (
"errors"
"testing"
"time"
)
func TestDo(t *testing.T) {
var sfErr error
cbCalled := false
sfCalled := false
sfSleep := 0 * time.Second
reset := func() {
cbCalled = false
sfCalled = false
sfErr = nil
}
sf := func() error {
sfCalled = true
time.Sleep(sfSleep)
return sfErr
}
cb := func() { cbCalled = true }
// SF is not slow
reset()
if err := Do(10*time.Millisecond, sf, cb); err != nil {
t.Fatalf("err: %s", err)
}
if !sfCalled {
t.Fatal("should call")
}
if cbCalled {
t.Fatal("should not call")
}
// SF is not slow (with error)
reset()
sfErr = errors.New("error")
if err := Do(10*time.Millisecond, sf, cb); err == nil {
t.Fatalf("err: %s", err)
}
if !sfCalled {
t.Fatal("should call")
}
if cbCalled {
t.Fatal("should not call")
}
// SF is slow
reset()
sfSleep = 50 * time.Millisecond
if err := Do(10*time.Millisecond, sf, cb); err != nil {
t.Fatalf("err: %s", err)
}
if !sfCalled {
t.Fatal("should call")
}
if !cbCalled {
t.Fatal("should call")
}
// SF is slow (with error)
reset()
sfErr = errors.New("error")
sfSleep = 50 * time.Millisecond
if err := Do(10*time.Millisecond, sf, cb); err == nil {
t.Fatalf("err: %s", err)
}
if !sfCalled {
t.Fatal("should call")
}
if !cbCalled {
t.Fatal("should call")
}
}