@@ -38,6 +38,7 @@ import (
38
38
"time"
39
39
40
40
"connectrpc.com/connect"
41
+ "github.com/flowchartsman/retry"
41
42
"github.com/hashicorp/memberlist"
42
43
"go.uber.org/atomic"
43
44
"google.golang.org/protobuf/types/known/timestamppb"
@@ -156,7 +157,7 @@ func (node *Node) Start(ctx context.Context) error {
156
157
AddError (node .config .Validate ()).
157
158
AddError (node .config .provider .Initialize ()).
158
159
AddError (node .config .provider .Register ()).
159
- AddError (node .join ()).
160
+ AddError (node .join (ctx )).
160
161
AddError (node .serve (ctx )).
161
162
Error (); err != nil {
162
163
node .mu .Unlock ()
@@ -231,17 +232,35 @@ func (node *Node) Put(ctx context.Context, request *connect.Request[internalpb.P
231
232
}
232
233
233
234
// Get is used to retrieve a key/value pair in a cluster of nodes
234
- // nolint
235
235
func (node * Node ) Get (ctx context.Context , request * connect.Request [internalpb.GetRequest ]) (* connect.Response [internalpb.GetResponse ], error ) {
236
236
node .mu .Lock ()
237
237
if ! node .started .Load () {
238
238
node .mu .Unlock ()
239
239
return nil , connect .NewError (connect .CodeFailedPrecondition , ErrNodeNotStarted )
240
240
}
241
241
242
+ ctx , cancelFn := context .WithTimeout (ctx , node .config .readTimeout )
243
+ defer cancelFn ()
244
+
242
245
req := request .Msg
243
- entry , err := node .delegate .Get (req .GetKey ())
244
- if err != nil {
246
+ var (
247
+ rerr error
248
+ entry * internalpb.Entry
249
+ )
250
+
251
+ retrier := retry .NewRetrier (2 , node .config .readTimeout , node .config .syncInterval )
252
+ if err := retrier .RunContext (ctx , func (ctx context.Context ) error {
253
+ select {
254
+ case <- ctx .Done ():
255
+ return ctx .Err ()
256
+ default :
257
+ entry , rerr = node .delegate .Get (req .GetKey ())
258
+ if rerr != nil {
259
+ return rerr
260
+ }
261
+ }
262
+ return nil
263
+ }); err != nil {
245
264
node .mu .Unlock ()
246
265
return nil , connect .NewError (connect .CodeNotFound , err )
247
266
}
@@ -342,13 +361,14 @@ func (node *Node) Peers() ([]*Member, error) {
342
361
// serve start the underlying http server
343
362
func (node * Node ) serve (ctx context.Context ) error {
344
363
// extract the actual TCP ip discoveryAddress
345
- host , port , err := tcp .GetHostPort (fmt .Sprintf ("%s:%d" , node .config .host , node .config .port ))
364
+ hostPort := net .JoinHostPort (node .config .host , strconv .Itoa (int (node .config .port )))
365
+ bindIP , err := tcp .GetBindIP (hostPort )
346
366
if err != nil {
347
367
return fmt .Errorf ("failed to resolve TCP discoveryAddress: %w" , err )
348
368
}
349
369
350
- node .config .WithHost (host )
351
- node .config .WithPort (uint16 (port ))
370
+ node .config .WithHost (bindIP )
371
+ node .config .WithPort (uint16 (node . config . port ))
352
372
353
373
// hook the node as the KV service handler
354
374
// TODO: add metric options to the handler
@@ -372,20 +392,29 @@ func (node *Node) serve(ctx context.Context) error {
372
392
}
373
393
374
394
// join attempts to join an existing cluster if node peers is provided
375
- func (node * Node ) join () error {
395
+ func (node * Node ) join (ctx context. Context ) error {
376
396
mlist , err := memberlist .Create (node .memberConfig )
377
397
if err != nil {
378
398
node .config .logger .Error (fmt .Errorf ("failed to create memberlist: %w" , err ))
379
399
return err
380
400
}
381
401
382
- // TODO: use a retry mechanism here
383
- peers , err := node .config .provider .DiscoverPeers ()
384
- if err != nil {
385
- node .config .logger .Error (fmt .Errorf ("failed to discover peers: %w" , err ))
402
+ ctx2 , cancel := context .WithTimeout (ctx , node .config .joinTimeout )
403
+ var peers []string
404
+ retrier := retry .NewRetrier (node .config .maxJoinAttempts , node .config .joinRetryInterval , node .config .joinRetryInterval )
405
+ if err := retrier .RunContext (ctx2 , func (ctx context.Context ) error { // nolint
406
+ peers , err = node .config .provider .DiscoverPeers ()
407
+ if err != nil {
408
+ return err
409
+ }
410
+ return nil
411
+ }); err != nil {
412
+ cancel ()
386
413
return err
387
414
}
388
415
416
+ cancel ()
417
+
389
418
// set the mlist
390
419
node .memberlist = mlist
391
420
if len (peers ) > 0 {
0 commit comments