master
go 55 lines 1.09 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package dyncfg
4
5 import (
6 "context"
7 "time"
8 )
9
10 const DefaultDownstreamHandoffCap = 10 * time.Second
11
12 type BoundedSendResult uint8
13
14 const (
15 BoundedSendOK BoundedSendResult = iota + 1
16 BoundedSendContextDone
17 BoundedSendTimeout
18 )
19
20 // BoundedSend sends value to ch using bounded wait:
21 // wait = min(remaining request deadline, maxWait), with maxWait used when no deadline exists.
22 func BoundedSend[T any](ctx context.Context, ch chan<- T, value T, maxWait time.Duration) BoundedSendResult {
23 if maxWait <= 0 {
24 maxWait = DefaultDownstreamHandoffCap
25 }
26 if ctx == nil {
27 ctx = context.Background()
28 }
29
30 wait := maxWait
31 if deadline, ok := ctx.Deadline(); ok {
32 remaining := time.Until(deadline)
33 if remaining <= 0 {
34 if ctx.Err() != nil {
35 return BoundedSendContextDone
36 }
37 return BoundedSendTimeout
38 }
39 if remaining < wait {
40 wait = remaining
41 }
42 }
43
44 timer := time.NewTimer(wait)
45 defer timer.Stop()
46
47 select {
48 case <-ctx.Done():
49 return BoundedSendContextDone
50 case ch <- value:
51 return BoundedSendOK
52 case <-timer.C:
53 return BoundedSendTimeout
54 }
55 }