github.com/MetalBlockchain/metalgo@v1.11.9/api/health/client.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package health
     5  
     6  import (
     7  	"context"
     8  	"time"
     9  
    10  	"github.com/MetalBlockchain/metalgo/utils/rpc"
    11  )
    12  
    13  var _ Client = (*client)(nil)
    14  
    15  // Client interface for Avalanche Health API Endpoint
    16  // For helpers to wait for Readiness, Health, or Liveness, see AwaitReady,
    17  // AwaitHealthy, and AwaitAlive.
    18  type Client interface {
    19  	// Readiness returns if the node has finished initialization
    20  	Readiness(ctx context.Context, tags []string, options ...rpc.Option) (*APIReply, error)
    21  	// Health returns a summation of the health of the node
    22  	Health(ctx context.Context, tags []string, options ...rpc.Option) (*APIReply, error)
    23  	// Liveness returns if the node is in need of a restart
    24  	Liveness(ctx context.Context, tags []string, options ...rpc.Option) (*APIReply, error)
    25  }
    26  
    27  // Client implementation for Avalanche Health API Endpoint
    28  type client struct {
    29  	requester rpc.EndpointRequester
    30  }
    31  
    32  // NewClient returns a client to interact with Health API endpoint
    33  func NewClient(uri string) Client {
    34  	return &client{requester: rpc.NewEndpointRequester(
    35  		uri + "/ext/health",
    36  	)}
    37  }
    38  
    39  func (c *client) Readiness(ctx context.Context, tags []string, options ...rpc.Option) (*APIReply, error) {
    40  	res := &APIReply{}
    41  	err := c.requester.SendRequest(ctx, "health.readiness", &APIArgs{Tags: tags}, res, options...)
    42  	return res, err
    43  }
    44  
    45  func (c *client) Health(ctx context.Context, tags []string, options ...rpc.Option) (*APIReply, error) {
    46  	res := &APIReply{}
    47  	err := c.requester.SendRequest(ctx, "health.health", &APIArgs{Tags: tags}, res, options...)
    48  	return res, err
    49  }
    50  
    51  func (c *client) Liveness(ctx context.Context, tags []string, options ...rpc.Option) (*APIReply, error) {
    52  	res := &APIReply{}
    53  	err := c.requester.SendRequest(ctx, "health.liveness", &APIArgs{Tags: tags}, res, options...)
    54  	return res, err
    55  }
    56  
    57  // AwaitReady polls the node every [freq] until the node reports ready.
    58  // Only returns an error if [ctx] returns an error.
    59  func AwaitReady(ctx context.Context, c Client, freq time.Duration, tags []string, options ...rpc.Option) (bool, error) {
    60  	return await(ctx, freq, c.Readiness, tags, options...)
    61  }
    62  
    63  // AwaitHealthy polls the node every [freq] until the node reports healthy.
    64  // Only returns an error if [ctx] returns an error.
    65  func AwaitHealthy(ctx context.Context, c Client, freq time.Duration, tags []string, options ...rpc.Option) (bool, error) {
    66  	return await(ctx, freq, c.Health, tags, options...)
    67  }
    68  
    69  // AwaitAlive polls the node every [freq] until the node reports liveness.
    70  // Only returns an error if [ctx] returns an error.
    71  func AwaitAlive(ctx context.Context, c Client, freq time.Duration, tags []string, options ...rpc.Option) (bool, error) {
    72  	return await(ctx, freq, c.Liveness, tags, options...)
    73  }
    74  
    75  func await(
    76  	ctx context.Context,
    77  	freq time.Duration,
    78  	check func(ctx context.Context, tags []string, options ...rpc.Option) (*APIReply, error),
    79  	tags []string,
    80  	options ...rpc.Option,
    81  ) (bool, error) {
    82  	ticker := time.NewTicker(freq)
    83  	defer ticker.Stop()
    84  
    85  	for {
    86  		res, err := check(ctx, tags, options...)
    87  		if err == nil && res.Healthy {
    88  			return true, nil
    89  		}
    90  
    91  		select {
    92  		case <-ticker.C:
    93  		case <-ctx.Done():
    94  			return false, ctx.Err()
    95  		}
    96  	}
    97  }