Class RestCapabilityDiscoveryMode

java.lang.Object
io.axoniq.framework.springcloud.discovery.RestCapabilityDiscoveryMode
All Implemented Interfaces:
CapabilityDiscoveryMode

public class RestCapabilityDiscoveryMode extends Object implements CapabilityDiscoveryMode
A CapabilityDiscoveryMode that asks each ServiceInstance for its MemberCapabilities over HTTP, against the endpoint served by MemberCapabilitiesController.

Because capabilities are requested again on every refresh and rarely change, responses are cached per instance and revalidated with a conditional If-None-Match request. An unchanged member answers 304 Not Modified with no body, so a steady-state cluster spends only the round trip. Cache entries are discarded when retainOnly(Set) reports that an instance is gone.

This application is identified by a node id generated when this mode is constructed, which MemberCapabilitiesController serves along with this application's capabilities. This application's own instance is asked like any other, and recognized by the node id it answers with.

Selecting this mode makes MemberCapabilitiesController a requirement: every member of the cluster must serve the same endpoint, or its peers cannot learn what it handles.

Failures are distinguished by kind, because they mean different things:

  • A client error means the instance is not serving this endpoint at all — a different service, or an older version of this one. It surfaces as a ServiceInstanceClientException so that IgnoreListingDiscoveryMode can stop asking for a while.
  • Any other failure — a refused connection, a timeout, a server error — means the instance is expected back. It yields MemberCapabilities.INCAPABLE under the node id the instance last answered with, keeping it in the routing ring as a member that currently handles nothing rather than removing it, so a brief outage does not reshuffle the routing of commands it would never have handled. An instance that never answered has no node id to keep, and is left out.
Since:
5.4.0
Author:
Allard Buijze, Steven van Beelen
  • Field Details

    • DEFAULT_CAPABILITIES_ENDPOINT

      public static final String DEFAULT_CAPABILITIES_ENDPOINT
      The path the capabilities endpoint is served under when none is configured.
      See Also:
    • DEFAULT_CAPABILITIES_TIMEOUT

      public static final Duration DEFAULT_CAPABILITIES_TIMEOUT
      How long an instance is given to answer a capabilities request when no other deadline is configured.

      Kept short deliberately: capabilities are asked for on every discovery round, so this bounds how long one unresponsive instance can hold up the round that rebuilds the routing ring. Applied by the Spring Boot autoconfiguration to the client it contributes for capabilities requests.

  • Constructor Details

    • RestCapabilityDiscoveryMode

      public RestCapabilityDiscoveryMode(org.springframework.web.client.RestClient restClient)
      Constructs a RestCapabilityDiscoveryMode requesting capabilities with the given restClient from the DEFAULT_CAPABILITIES_ENDPOINT.
      Parameters:
      restClient - the client used to request the capabilities of other members
    • RestCapabilityDiscoveryMode

      public RestCapabilityDiscoveryMode(org.springframework.web.client.RestClient restClient, String capabilitiesEndpoint)
      Constructs a RestCapabilityDiscoveryMode requesting capabilities with the given restClient from the given capabilitiesEndpoint.

      The capabilitiesEndpoint must match the path MemberCapabilitiesController is mapped to on every member of the cluster.

      Parameters:
      restClient - the client used to request the capabilities of other members
      capabilitiesEndpoint - the path, relative to a member's base URI, the capabilities endpoint is served under
  • Method Details

    • localNodeId

      public String localNodeId()
      Description copied from interface: CapabilityDiscoveryMode
      Returns the identifier of this application, which it reports to other members along with its capabilities.

      Unique to the running process: an application that restarts is a new member, which matters because it has not seen what the previous process did.

      Specified by:
      localNodeId in interface CapabilityDiscoveryMode
      Returns:
      the identifier of this application
    • updateLocalCapabilities

      public void updateLocalCapabilities(MemberCapabilities capabilities)
      Description copied from interface: CapabilityDiscoveryMode
      Publishes the given capabilities as this application's own, replacing whatever was published before.

      Called whenever a command or query handler is subscribed to, or unsubscribed from, this application's connector.

      Specified by:
      updateLocalCapabilities in interface CapabilityDiscoveryMode
      Parameters:
      capabilities - the messages this application handles, and the command load it asks for
    • discover

      public Optional<MemberAdvertisement> discover(org.springframework.cloud.client.ServiceInstance serviceInstance)
      Description copied from interface: CapabilityDiscoveryMode
      Discovers which member the given serviceInstance is, and what it handles.

      An empty Optional means the instance should be left out of the routing ring entirely — it is not a member of this cluster, or is not currently answering for one. That differs from an advertisement carrying MemberCapabilities.INCAPABLE, which keeps the instance in the ring as a member that handles nothing.

      This application's own instance is discovered like any other, answering with this application's node id.

      Called concurrently, once per discovered instance, for every instance of one discovery round. Implementations must therefore be thread-safe.

      Specified by:
      discover in interface CapabilityDiscoveryMode
      Parameters:
      serviceInstance - the instance to discover
      Returns:
      the member the given serviceInstance is and what it handles, or Optional.empty() when it should not be part of the routing ring
    • retainOnly

      public void retainOnly(Set<ServiceInstanceKey> knownInstances)
      Description copied from interface: CapabilityDiscoveryMode
      Signals that the given knownInstances are the only instances discovery currently reports, allowing this mode to discard whatever it remembers about instances that have gone away.

      Called at the end of each discovery round. Implementations that keep no per-instance state need not do anything, which is what this default implementation does.

      Specified by:
      retainOnly in interface CapabilityDiscoveryMode
      Parameters:
      knownInstances - the keys of every instance the current discovery round reported
    • localCapabilities

      public MemberCapabilities localCapabilities()
      Description copied from interface: CapabilityDiscoveryMode
      Returns this application's own capabilities, as last published through CapabilityDiscoveryMode.updateLocalCapabilities(MemberCapabilities).

      A mode is told what this application handles so it can publish it; that same knowledge is what MemberCapabilitiesController serves to other members, which is why reading it back is part of this contract rather than of any one implementation.

      Specified by:
      localCapabilities in interface CapabilityDiscoveryMode
      Returns:
      this application's own capabilities, or MemberCapabilities.INCAPABLE while nothing has been published yet