@@ -42,51 +42,43 @@ func Until(ctx context.Context, d time.Duration, fn LongPollFunc) (ok bool, err
42
42
// budget is communicated via the provided context. This is a defence measure to not have accidental
43
43
// long running routines. If no duration is given (0) the long poll will have exactly one execution.
44
44
func (c Config ) LongPollUntil (ctx context.Context , d time.Duration , fn LongPollFunc ) (ok bool , err error ) {
45
- until := time . Now ()
45
+ var cancel context. CancelFunc
46
46
47
47
if d != 0 {
48
- if d < c .MinWaitTime { // guard lower bound
49
- until = until .Add (c .MinWaitTime )
50
- } else if d > c .MaxWaitTime { // guard upper bound
51
- until = until .Add (c .MaxWaitTime )
52
- } else {
53
- until = until .Add (d )
48
+ if d < c .MinWaitTime {
49
+ d = c .MinWaitTime
50
+ } else if d > c .MaxWaitTime {
51
+ d = c .MaxWaitTime
54
52
}
53
+
54
+ ctx , cancel = context .WithTimeout (ctx , d )
55
+ defer cancel ()
55
56
}
56
57
57
- fnCtx , cancel := context .WithDeadline (ctx , until )
58
- defer cancel ()
58
+ doneCh := make (chan struct {})
59
59
60
- loop:
61
- for {
62
- ok , err = fn (fnCtx )
63
- if err != nil {
64
- return
65
- }
60
+ go func () {
61
+ defer func () {
62
+ doneCh <- struct {}{}
63
+ }()
66
64
67
- // fn returns true, break the loop
68
- if ok {
69
- break
70
- }
65
+ for {
66
+ ok , err = fn (ctx )
67
+ if ok || err != nil || d == 0 {
68
+ return
69
+ }
71
70
72
- // no long polling
73
- if d <= 0 {
74
- break
75
- }
71
+ select {
72
+ case <- ctx .Done ():
73
+ err = ctx .Err ()
76
74
77
- // long pooling desired?
78
- if ! time .Now (). Add ( c .RetryTime ). Before ( until ) {
79
- break
75
+ return
76
+ case <- time .After ( c .RetryTime ):
77
+ }
80
78
}
79
+ }()
81
80
82
- select {
83
- // handle context cancelation
84
- case <- ctx .Done ():
85
- return false , ctx .Err ()
86
- case <- time .After (c .RetryTime ):
87
- continue loop
88
- }
89
- }
81
+ <- doneCh
90
82
91
83
return
92
84
}
0 commit comments