|
|
|
@ -26,65 +26,59 @@ const (
|
|
|
|
|
// StreamingHealthServices supports fetching discovering service instances via the
|
|
|
|
|
// catalog using the streaming gRPC endpoint.
|
|
|
|
|
type StreamingHealthServices struct {
|
|
|
|
|
client submatview.StreamingClient
|
|
|
|
|
logger hclog.Logger
|
|
|
|
|
RegisterOptionsBlockingRefresh
|
|
|
|
|
deps MaterializerDeps
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewStreamingHealthServices creates a cache-type for watching for service
|
|
|
|
|
// health results via streaming updates.
|
|
|
|
|
func NewStreamingHealthServices(client submatview.StreamingClient, logger hclog.Logger) *StreamingHealthServices {
|
|
|
|
|
return &StreamingHealthServices{
|
|
|
|
|
client: client,
|
|
|
|
|
logger: logger,
|
|
|
|
|
}
|
|
|
|
|
func NewStreamingHealthServices(deps MaterializerDeps) *StreamingHealthServices {
|
|
|
|
|
return &StreamingHealthServices{deps: deps}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type MaterializerDeps struct {
|
|
|
|
|
Client submatview.StreamingClient
|
|
|
|
|
Logger hclog.Logger
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fetch implements cache.Type
|
|
|
|
|
func (c *StreamingHealthServices) Fetch(opts cache.FetchOptions, req cache.Request) (cache.FetchResult, error) {
|
|
|
|
|
// The request should be a ServiceSpecificRequest.
|
|
|
|
|
reqReal, ok := req.(*structs.ServiceSpecificRequest)
|
|
|
|
|
if !ok {
|
|
|
|
|
return cache.FetchResult{}, fmt.Errorf(
|
|
|
|
|
"Internal cache failure: request wrong type: %T", req)
|
|
|
|
|
if opts.LastResult != nil && opts.LastResult.State != nil {
|
|
|
|
|
return opts.LastResult.State.(*submatview.Materializer).Fetch(opts)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r := submatview.Request{
|
|
|
|
|
SubscribeRequest: pbsubscribe.SubscribeRequest{
|
|
|
|
|
Topic: pbsubscribe.Topic_ServiceHealth,
|
|
|
|
|
Key: reqReal.ServiceName,
|
|
|
|
|
Token: reqReal.Token,
|
|
|
|
|
Index: reqReal.MinQueryIndex,
|
|
|
|
|
Datacenter: reqReal.Datacenter,
|
|
|
|
|
},
|
|
|
|
|
Filter: reqReal.Filter,
|
|
|
|
|
srvReq := req.(*structs.ServiceSpecificRequest)
|
|
|
|
|
subReq := pbsubscribe.SubscribeRequest{
|
|
|
|
|
Topic: pbsubscribe.Topic_ServiceHealth,
|
|
|
|
|
Key: srvReq.ServiceName,
|
|
|
|
|
Token: srvReq.Token,
|
|
|
|
|
Index: srvReq.MinQueryIndex,
|
|
|
|
|
Datacenter: srvReq.Datacenter,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Connect requests need a different topic
|
|
|
|
|
if reqReal.Connect {
|
|
|
|
|
r.Topic = pbsubscribe.Topic_ServiceHealthConnect
|
|
|
|
|
if srvReq.Connect {
|
|
|
|
|
subReq.Topic = pbsubscribe.Topic_ServiceHealthConnect
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
view, err := c.getMaterializedView(opts, r)
|
|
|
|
|
view, err := newMaterializer(c.deps, subReq, srvReq.Filter)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return cache.FetchResult{}, err
|
|
|
|
|
}
|
|
|
|
|
return view.Fetch(opts)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *StreamingHealthServices) getMaterializedView(opts cache.FetchOptions, r submatview.Request) (*submatview.Materializer, error) {
|
|
|
|
|
if opts.LastResult != nil && opts.LastResult.State != nil {
|
|
|
|
|
return opts.LastResult.State.(*submatview.Materializer), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state, err := newHealthViewState(r.Filter)
|
|
|
|
|
func newMaterializer(
|
|
|
|
|
d MaterializerDeps,
|
|
|
|
|
r pbsubscribe.SubscribeRequest,
|
|
|
|
|
filter string,
|
|
|
|
|
) (*submatview.Materializer, error) {
|
|
|
|
|
state, err := newHealthViewState(filter)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
ctx, cancel := context.WithCancel(context.TODO())
|
|
|
|
|
view := submatview.NewMaterializer(submatview.ViewDeps{
|
|
|
|
|
State: state,
|
|
|
|
|
Client: c.client,
|
|
|
|
|
Logger: c.logger,
|
|
|
|
|
Client: d.Client,
|
|
|
|
|
Logger: d.Logger,
|
|
|
|
|
Waiter: &retry.Waiter{
|
|
|
|
|
MinFailures: 1,
|
|
|
|
|
MinWait: 0,
|
|
|
|
@ -99,11 +93,6 @@ func (c *StreamingHealthServices) getMaterializedView(opts cache.FetchOptions, r
|
|
|
|
|
return view, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SupportsBlocking implements cache.Type
|
|
|
|
|
func (c *StreamingHealthServices) SupportsBlocking() bool {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newHealthViewState(filterExpr string) (submatview.View, error) {
|
|
|
|
|
s := &healthViewState{state: make(map[string]structs.CheckServiceNode)}
|
|
|
|
|
|
|
|
|
@ -116,16 +105,6 @@ func newHealthViewState(filterExpr string) (submatview.View, error) {
|
|
|
|
|
return s, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// StreamingClient implements StreamingCacheType
|
|
|
|
|
func (c *StreamingHealthServices) StreamingClient() submatview.StreamingClient {
|
|
|
|
|
return c.client
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Logger implements StreamingCacheType
|
|
|
|
|
func (c *StreamingHealthServices) Logger() hclog.Logger {
|
|
|
|
|
return c.logger
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// healthViewState implements View for storing the view state
|
|
|
|
|
// of a service health result. We store it as a map to make updates and
|
|
|
|
|
// deletions a little easier but we could just store a result type
|
|
|
|
|