mirror of
https://github.com/status-im/consul.git
synced 2025-01-10 22:06:20 +00:00
529f252d5c
This new package provides a client agent implementation of an interface for fetching the health of services. This approach has a number of benefits: 1. It provides a much more explicit interface. Instead of everything dependency on `RPC()` and `Cache.Get()` for many unrelated things they can depend on a type that are named according to the behaviour it provides. 2. It gives us a single place to vary the behaviour and migrate to a new form of RPC (gRPC). The current implementation has two options (cache, or direct RPC), and in the future we will have more. It is also a great opporunity to start adding `context.Context` args to these operations, which in the future will allow us to cancel the operations. 3. As a concequence of the first, in the Server agent where we make these calls we can replace the current in-memory RPC calls with a thin adapter for the real method. This removes the `net/rpc` machinery from the call in places where it is not needed. This new package is quite small right now, but I think we can expect it to grow to a more reasonable size as other RPC calls are replaced. This change also happens to replace two very similar implementations with a single implementation.
65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package health
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/hashicorp/consul/agent/cache"
|
|
cachetype "github.com/hashicorp/consul/agent/cache-types"
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
)
|
|
|
|
type Client struct {
|
|
NetRPC NetRPC
|
|
Cache CacheGetter
|
|
}
|
|
|
|
type NetRPC interface {
|
|
RPC(method string, args interface{}, reply interface{}) error
|
|
}
|
|
|
|
type CacheGetter interface {
|
|
Get(ctx context.Context, t string, r cache.Request) (interface{}, cache.ResultMeta, error)
|
|
}
|
|
|
|
func (c *Client) ServiceNodes(
|
|
ctx context.Context,
|
|
req structs.ServiceSpecificRequest,
|
|
) (structs.IndexedCheckServiceNodes, cache.ResultMeta, error) {
|
|
out, md, err := c.getServiceNodes(ctx, req)
|
|
if err != nil {
|
|
return out, md, err
|
|
}
|
|
|
|
// TODO: DNSServer emitted a metric here, do we still need it?
|
|
if req.QueryOptions.AllowStale && req.QueryOptions.MaxStaleDuration > 0 && out.QueryMeta.LastContact > req.MaxStaleDuration {
|
|
req.AllowStale = false
|
|
err := c.NetRPC.RPC("Health.ServiceNodes", &req, &out)
|
|
return out, cache.ResultMeta{}, err
|
|
}
|
|
|
|
return out, md, err
|
|
}
|
|
|
|
func (c *Client) getServiceNodes(
|
|
ctx context.Context,
|
|
req structs.ServiceSpecificRequest,
|
|
) (structs.IndexedCheckServiceNodes, cache.ResultMeta, error) {
|
|
var out structs.IndexedCheckServiceNodes
|
|
|
|
if !req.QueryOptions.UseCache {
|
|
err := c.NetRPC.RPC("Health.ServiceNodes", &req, &out)
|
|
return out, cache.ResultMeta{}, err
|
|
}
|
|
|
|
raw, md, err := c.Cache.Get(ctx, cachetype.HealthServicesName, &req)
|
|
if err != nil {
|
|
return out, md, err
|
|
}
|
|
|
|
value, ok := raw.(*structs.IndexedCheckServiceNodes)
|
|
if !ok {
|
|
panic("wrong response type for cachetype.HealthServicesName")
|
|
}
|
|
return *value, md, nil
|
|
}
|