-
Notifications
You must be signed in to change notification settings - Fork 118
Expand file tree
/
Copy pathutil.go
More file actions
101 lines (89 loc) · 2.34 KB
/
util.go
File metadata and controls
101 lines (89 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package util
import (
"context"
"fmt"
"reflect"
"time"
"github.com/coder/quartz"
"github.com/danielgtaylor/huma/v2"
"golang.org/x/xerrors"
)
type WaitTimeout struct {
Timeout time.Duration
MinInterval time.Duration
MaxInterval time.Duration
InitialWait bool
Clock quartz.Clock
}
var WaitTimedOut = xerrors.New("timeout waiting for condition")
// WaitFor waits for a condition to be true or the timeout to expire.
// It will wait for the condition to be true with exponential backoff.
// A single sleep timer is reused across iterations via Reset so that
// mock-clock tests always have a pending timer to advance.
func WaitFor(ctx context.Context, timeout WaitTimeout, condition func() (bool, error)) error {
clock := timeout.Clock
if clock == nil {
clock = quartz.NewReal()
}
minInterval := timeout.MinInterval
maxInterval := timeout.MaxInterval
timeoutDuration := timeout.Timeout
if minInterval == 0 {
minInterval = 10 * time.Millisecond
}
if maxInterval == 0 {
maxInterval = 500 * time.Millisecond
}
if timeoutDuration == 0 {
timeoutDuration = 10 * time.Second
}
if minInterval > maxInterval {
return xerrors.Errorf("minInterval is greater than maxInterval")
}
timeoutTimer := clock.NewTimer(timeoutDuration)
defer timeoutTimer.Stop()
interval := minInterval
sleepTimer := clock.NewTimer(interval)
defer sleepTimer.Stop()
waitForTimer := timeout.InitialWait
for {
if waitForTimer {
select {
case <-sleepTimer.C:
case <-ctx.Done():
return ctx.Err()
case <-timeoutTimer.C:
return WaitTimedOut
}
}
waitForTimer = true
ok, err := condition()
if err != nil {
return err
}
if ok {
return nil
}
interval = min(interval*2, maxInterval)
if !sleepTimer.Stop() {
select {
case <-sleepTimer.C:
default:
}
}
sleepTimer.Reset(interval)
}
}
// based on https://github.com/danielgtaylor/huma/issues/621#issuecomment-2456588788
func OpenAPISchema[T ~string](r huma.Registry, enumName string, values []T) *huma.Schema {
if r.Map()[enumName] == nil {
schemaRef := r.Schema(reflect.TypeOf(""), true, enumName)
schemaRef.Title = enumName
schemaRef.Examples = []any{values[0]}
for _, v := range values {
schemaRef.Enum = append(schemaRef.Enum, string(v))
}
r.Map()[enumName] = schemaRef
}
return &huma.Schema{Ref: fmt.Sprintf("#/components/schemas/%s", enumName)}
}