|
17 | 17 | package edge_apis |
18 | 18 |
|
19 | 19 | import ( |
20 | | - "github.com/go-openapi/runtime" |
21 | | - "github.com/michaelquigley/pfxlog" |
22 | | - cmap "github.com/orcaman/concurrent-map/v2" |
23 | | - errors "github.com/pkg/errors" |
24 | 20 | "math/rand/v2" |
25 | 21 | "net" |
26 | 22 | "net/url" |
27 | 23 | "slices" |
28 | 24 | "sync/atomic" |
29 | 25 | "time" |
| 26 | + |
| 27 | + "github.com/go-openapi/runtime" |
| 28 | + "github.com/michaelquigley/pfxlog" |
| 29 | + cmap "github.com/orcaman/concurrent-map/v2" |
| 30 | + errors "github.com/pkg/errors" |
30 | 31 | ) |
31 | 32 |
|
32 | 33 | type ApiClientTransport struct { |
@@ -151,23 +152,14 @@ func (c *ClientTransportPoolRandom) TryTransportsForOp(operation *runtime.Client |
151 | 152 | return result, err |
152 | 153 | } |
153 | 154 |
|
154 | | -func (c *ClientTransportPoolRandom) IterateRandomTransport() <-chan *ApiClientTransport { |
155 | | - var transportsToTry []*cmap.Tuple[string, *ApiClientTransport] |
156 | | - for tpl := range c.pool.IterBuffered() { |
157 | | - transportsToTry = append(transportsToTry, &tpl) |
158 | | - } |
159 | | - |
160 | | - ch := make(chan *ApiClientTransport, len(transportsToTry)) |
161 | | - |
162 | | - go func() { |
163 | | - for len(transportsToTry) > 0 { |
164 | | - var transportTpl *cmap.Tuple[string, *ApiClientTransport] |
165 | | - transportTpl, transportsToTry = selectAndRemoveRandom(transportsToTry, nil) |
166 | | - ch <- transportTpl.Val |
167 | | - } |
168 | | - }() |
| 155 | +func (c *ClientTransportPoolRandom) IterateRandomTransport() []*ApiClientTransport { |
| 156 | + var result []*ApiClientTransport |
| 157 | + c.pool.IterCb(func(_ string, v *ApiClientTransport) { |
| 158 | + result = append(result, v) |
| 159 | + }) |
169 | 160 |
|
170 | | - return ch |
| 161 | + Randomize(result) |
| 162 | + return result |
171 | 163 | } |
172 | 164 |
|
173 | 165 | func (c *ClientTransportPoolRandom) TryTransportForF(cb func(*ApiClientTransport) (any, error)) (any, error) { |
@@ -200,12 +192,12 @@ func (c *ClientTransportPoolRandom) TryTransportForF(cb func(*ApiClientTransport |
200 | 192 | // either no active or active failed, lets start trying them at random |
201 | 193 | pfxlog.Logger().Debug("trying random transports from pool") |
202 | 194 |
|
203 | | - ch := c.IterateRandomTransport() |
| 195 | + transports := c.IterateRandomTransport() |
204 | 196 |
|
205 | 197 | var lastResult any |
206 | 198 | lastErr := errors.New("no transports to try, active transport already failed or was nil") //default err should never be returned |
207 | 199 | attempts := 0 |
208 | | - for transport := range ch { |
| 200 | + for _, transport := range transports { |
209 | 201 | // skip the already attempted active key |
210 | 202 | if activeKey != "" && transport.ApiUrl.String() == activeKey { |
211 | 203 | continue |
@@ -258,6 +250,16 @@ func errorIndicatesControllerSwap(err error) bool { |
258 | 250 | return false |
259 | 251 | } |
260 | 252 |
|
| 253 | +func Randomize[T any](s []T) { |
| 254 | + for i := 0; i < len(s); i++ { |
| 255 | + idx := rand.IntN(len(s)) |
| 256 | + e1 := s[i] |
| 257 | + e2 := s[idx] |
| 258 | + s[i] = e2 |
| 259 | + s[idx] = e1 |
| 260 | + } |
| 261 | +} |
| 262 | + |
261 | 263 | func selectAndRemoveRandom[T any](slice []T, zero T) (selected T, modifiedSlice []T) { |
262 | 264 | if len(slice) == 0 { |
263 | 265 | return zero, slice |
|
0 commit comments