File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ package slowmessage
2+
3+ import (
4+ "time"
5+ )
6+
7+ // SlowFunc is the function that could be slow. Usually, you'll have to
8+ // wrap an existing function in a lambda to make it match this type signature.
9+ type SlowFunc func () error
10+
11+ // CallbackFunc is the function that is triggered when the threshold is reached.
12+ type CallbackFunc func ()
13+
14+ // Do calls sf. If threshold time has passed, cb is called. Note that this
15+ // call will be made concurrently to sf still running.
16+ func Do (threshold time.Duration , sf SlowFunc , cb CallbackFunc ) error {
17+ // Call the slow function
18+ errCh := make (chan error , 1 )
19+ go func () {
20+ errCh <- sf ()
21+ }()
22+
23+ // Wait for it to complete or the threshold to pass
24+ select {
25+ case err := <- errCh :
26+ return err
27+ case <- time .After (threshold ):
28+ // Threshold reached, call the callback
29+ cb ()
30+ }
31+
32+ // Wait an indefinite amount of time for it to finally complete
33+ return <- errCh
34+ }
Original file line number Diff line number Diff line change 1+ package slowmessage
2+
3+ import (
4+ "errors"
5+ "testing"
6+ "time"
7+ )
8+
9+ func TestDo (t * testing.T ) {
10+ var sfErr error
11+ cbCalled := false
12+ sfCalled := false
13+ sfSleep := 0 * time .Second
14+
15+ reset := func () {
16+ cbCalled = false
17+ sfCalled = false
18+ sfErr = nil
19+ }
20+ sf := func () error {
21+ sfCalled = true
22+ time .Sleep (sfSleep )
23+ return sfErr
24+ }
25+ cb := func () { cbCalled = true }
26+
27+ // SF is not slow
28+ reset ()
29+ if err := Do (10 * time .Millisecond , sf , cb ); err != nil {
30+ t .Fatalf ("err: %s" , err )
31+ }
32+
33+ if ! sfCalled {
34+ t .Fatal ("should call" )
35+ }
36+ if cbCalled {
37+ t .Fatal ("should not call" )
38+ }
39+
40+ // SF is not slow (with error)
41+ reset ()
42+ sfErr = errors .New ("error" )
43+ if err := Do (10 * time .Millisecond , sf , cb ); err == nil {
44+ t .Fatalf ("err: %s" , err )
45+ }
46+
47+ if ! sfCalled {
48+ t .Fatal ("should call" )
49+ }
50+ if cbCalled {
51+ t .Fatal ("should not call" )
52+ }
53+
54+ // SF is slow
55+ reset ()
56+ sfSleep = 50 * time .Millisecond
57+ if err := Do (10 * time .Millisecond , sf , cb ); err != nil {
58+ t .Fatalf ("err: %s" , err )
59+ }
60+
61+ if ! sfCalled {
62+ t .Fatal ("should call" )
63+ }
64+ if ! cbCalled {
65+ t .Fatal ("should call" )
66+ }
67+
68+ // SF is slow (with error)
69+ reset ()
70+ sfErr = errors .New ("error" )
71+ sfSleep = 50 * time .Millisecond
72+ if err := Do (10 * time .Millisecond , sf , cb ); err == nil {
73+ t .Fatalf ("err: %s" , err )
74+ }
75+
76+ if ! sfCalled {
77+ t .Fatal ("should call" )
78+ }
79+ if ! cbCalled {
80+ t .Fatal ("should call" )
81+ }
82+ }
You can’t perform that action at this time.
0 commit comments