Class SpringCloudAutoConfiguration.ConnectorConfiguration

java.lang.Object
io.axoniq.framework.springboot.autoconfig.SpringCloudAutoConfiguration.ConnectorConfiguration
Enclosing class:
SpringCloudAutoConfiguration

@Configuration(proxyBeanMethods=false) @ConditionalOnProperty(name="axon.springcloud.enabled", havingValue="true", matchIfMissing=true) public static class SpringCloudAutoConfiguration.ConnectorConfiguration extends Object
The connector's own beans, registered unless axon.springcloud.enabled is set to false.

Nested so that the property switches these beans off while leaving SpringCloudAutoConfiguration.disableSpringCloudConfigurationEnhancer() reachable — a class-level condition would switch that off too, and the service-loaded enhancer would go on registering a connector regardless.

Since:
5.4.0
Author:
Allard Buijze
  • Constructor Details

    • ConnectorConfiguration

      public ConnectorConfiguration()
  • Method Details

    • axoniqSpringCloudRestClient

      @Bean("axoniqSpringCloudRestClient") @ConditionalOnMissingBean(name="axoniqSpringCloudRestClient") public org.springframework.web.client.RestClient axoniqSpringCloudRestClient(org.springframework.beans.factory.ObjectProvider<org.springframework.web.client.RestClient.Builder> builderProvider, SpringCloudProperties properties)
      Bean creation method for the RestClient used to send commands to other members.

      Built from the application's own RestClient.Builder when it has one, so that whatever it configured there — a load balancer, authentication, timeouts — applies to inter-member traffic as well. When the application supplies no builder, the client is given timeouts of its own: without them a member that accepts a connection and then answers nothing holds the sending thread for as long as the operating system allows, outliving the dispatcher's own reply deadline, which bounds the returned future but not the exchange behind it.

      Parameters:
      builderProvider - provides the application's RestClient.Builder, if it has one
      properties - the Spring Cloud connector specific properties set by the application
      Returns:
      the client used to reach other members of the cluster
    • axoniqSpringCloudQueryRestClient

      @Bean("axoniqSpringCloudQueryRestClient") @ConditionalOnMissingBean(name="axoniqSpringCloudQueryRestClient") public org.springframework.web.client.RestClient axoniqSpringCloudQueryRestClient(org.springframework.beans.factory.ObjectProvider<org.springframework.web.client.RestClient.Builder> builderProvider)
      Bean creation method for the RestClient used to send queries and subscription queries to other members.

      Built from the application's own RestClient.Builder when it has one, keeping what it configured there, such as interceptors adding authentication, but always on a transport of its own: a JDK client with a connect timeout and no read timeout, which opens a connection per stream rather than borrowing one from a bounded pool. The dispatcher bounds the streams itself, with a deadline per query and a silence check per subscription.

      Because the transport is this client's own, transport settings of the application's client do not reach it, such as an SSL bundle configured for it or a custom request factory on the builder. Settings the JVM applies to every connection still do. An application whose members trust each other through an SSL bundle, or authenticate each other with client certificates, defines a bean named SpringCloudAutoConfiguration.QUERY_REST_CLIENT_BEAN itself, keeping it free of a read timeout and of a bounded connection pool. The same holds for the client named SpringCloudAutoConfiguration.CAPABILITIES_REST_CLIENT_BEAN, which is built without the application's builder altogether.

      Parameters:
      builderProvider - provides the application's RestClient.Builder, if it has one
      Returns:
      the client used to send queries and subscription queries to other members
    • axoniqSpringCloudCapabilitiesRestClient

      @Bean("axoniqSpringCloudCapabilitiesRestClient") @ConditionalOnMissingBean(name="axoniqSpringCloudCapabilitiesRestClient") public org.springframework.web.client.RestClient axoniqSpringCloudCapabilitiesRestClient(SpringCloudProperties properties)
      Bean creation method for the RestClient used to ask other instances for their capabilities.

      Separate from the client commands are sent with, because the two need opposite deadlines. A command may legitimately take as long as the handler needs, while a capabilities request happens on every discovery round and must not outlast it — one unresponsive instance would otherwise hold up the round that rebuilds the routing ring for every member.

      Parameters:
      properties - the connector's properties
      Returns:
      the client used to ask other instances for their capabilities
    • axoniqSpringCloudCapabilityDiscoveryMode

      @Bean @ConditionalOnMissingBean public CapabilityDiscoveryMode axoniqSpringCloudCapabilityDiscoveryMode(@Qualifier("axoniqSpringCloudCapabilitiesRestClient") org.springframework.web.client.RestClient restClient, SpringCloudProperties properties)
      Bean creation method for the CapabilityDiscoveryMode used to learn what each discovered instance handles.

      Combines the REST mode — the only way capabilities can travel, since service instance metadata is fixed at registration time — with the ignore list that keeps unrelated services from being asked on every heartbeat.

      Parameters:
      restClient - the client used to reach other members
      properties - the connector's properties
      Returns:
      the mode used to discover the capabilities of other members
    • axoniqSpringCloudMemberDiscovery

      @Bean @ConditionalOnMissingBean public SpringCloudMemberDiscovery axoniqSpringCloudMemberDiscovery(org.springframework.beans.factory.ObjectProvider<org.springframework.cloud.client.discovery.DiscoveryClient> discoveryClientProvider, CapabilityDiscoveryMode discoveryMode, org.springframework.beans.factory.ObjectProvider<Predicate<org.springframework.cloud.client.ServiceInstance>> instanceFilterProvider, SpringCloudProperties properties, @Qualifier("axoniqSpringCloudDiscoveryExecutor") ExecutorService discoveryExecutor, @Qualifier("axoniqSpringCloudQueryScheduler") ScheduledExecutorService scheduler)
      Bean creation method for the SpringCloudMemberDiscovery maintaining the routing ring from what Spring Cloud Discovery reports.

      An application can narrow which discovered instances are considered at all by contributing a Predicate<ServiceInstance> bean. That is worth doing on a registry holding many services: instances rejected by the predicate are never asked for their capabilities, which is cheaper than letting the ignore list learn about them one heartbeat at a time. Every instance is considered when no such bean is present.

      Capabilities are refreshed every SpringCloudProperties.getCapabilitiesRefreshInterval(), as decided on the query scheduler. That scheduler only hands the refresh to the discovery executor, which is where the requests are made, so nothing on it blocks.

      Parameters:
      discoveryClientProvider - provides the client reporting the service instances making up the cluster
      discoveryMode - the mode used to discover the capabilities of other members
      instanceFilterProvider - provides the filter deciding which discovered instances are considered
      properties - the connector's properties
      discoveryExecutor - the executor discovery rounds and their capability requests run on
      scheduler - the scheduler deciding when capabilities are due a refresh
      Returns:
      the discovery maintaining the routing ring
    • axoniqSpringCloudMembershipTrigger

      @Bean public org.springframework.context.ApplicationListener<org.springframework.context.ApplicationEvent> axoniqSpringCloudMembershipTrigger(SpringCloudMemberDiscovery discovery)
      Bean creation method for the ApplicationListener starting a membership round whenever Spring Cloud Discovery signals that the instances it reports may have changed.

      That is on every HeartbeatEvent, which Eureka publishes on every registry fetch and Spring Cloud Kubernetes whenever the set of endpoints changes, and on the InstanceRegisteredEvent published by discovery implementations that register this application themselves, so that it does not wait for the next heartbeat to learn about the cluster. The round runs on the discovery executor, so the thread publishing the event does not wait on it.

      Parameters:
      discovery - the discovery maintaining the routing ring
      Returns:
      the listener starting a membership round on discovery's signals
    • axoniqSpringCloudDiscoveryExecutor

      @Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudDiscoveryExecutor") @ConditionalOnMissingBean(name="axoniqSpringCloudDiscoveryExecutor") public ExecutorService axoniqSpringCloudDiscoveryExecutor()
      Bean creation method for the ExecutorService discovery rounds, and the capability requests within them, run on.

      A virtual-thread-per-task executor by default, as the work on it is blocking HTTP calls, one per discovered instance, concurrently. An application can supply its own under the "axoniqSpringCloudDiscoveryExecutor" name. A round waits for the requests it makes, so that executor must run more than one task at a time.

      Shut down with shutdownNow rather than the ExecutorService.close() Spring would infer, so that shutting down does not wait for a round still asking an instance that no longer answers.

      Returns:
      the executor discovery rounds run on
    • axoniqSpringCloudDispatchExecutor

      @Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudDispatchExecutor") @ConditionalOnMissingBean(name="axoniqSpringCloudDispatchExecutor") public ExecutorService axoniqSpringCloudDispatchExecutor()
      Bean creation method for the Executor the blocking HTTP exchanges with other members run on.

      A virtual-thread-per-task executor, because the work on it is a blocking HTTP call and nothing else. Sizing a platform thread pool for that would cap the messages this member can have in flight for no reason other than the pool's own size.

      Shut down with shutdownNow rather than the destroy method Spring would infer. That would be ExecutorService.close(), which waits for every task to finish — and a task here is the reading of a query's response stream, which lasts as long as the answering member keeps it open. Shutting down the application would then wait on members it is no longer talking to. The connector's own shutdown already waits for queries still in flight, in the OUTBOUND_QUERY_CONNECTORS phase, so by the time this runs the threads left are the ones nothing is waiting for.

      Returns:
      the executor inter-member dispatches run on
    • axoniqSpringCloudQueryScheduler

      @Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudQueryScheduler") @ConditionalOnMissingBean(name="axoniqSpringCloudQueryScheduler") public ScheduledExecutorService axoniqSpringCloudQueryScheduler()
      Bean creation method for the ScheduledExecutorService deciding when a query's deadline has passed, when a subscription has been silent for too long, and when a subscription being answered is due a keep-alive.

      A cancelled deadline is removed from its queue rather than left to elapse, so a query answered promptly does not keep its responses reachable until the deadline would have fired.

      A single thread carries all of it, which it can because nothing scheduled here blocks: the work is deciding that something is due, and the one due thing that blocks -- writing a keep-alive to a subscriber -- is handed to axoniqSpringCloudKeepAliveExecutor() instead.

      Returns:
      the scheduler query timing runs on
    • axoniqSpringCloudRemoteCommandDispatcher

      @Bean @ConditionalOnMissingBean public RemoteCommandDispatcher axoniqSpringCloudRemoteCommandDispatcher(@Qualifier("axoniqSpringCloudRestClient") org.springframework.web.client.RestClient restClient, @Qualifier("axoniqSpringCloudDispatchExecutor") Executor executor, SpringCloudProperties properties, org.springframework.beans.factory.ObjectProvider<MessageConverter> converterProvider)
      Bean creation method for the RemoteCommandDispatcher sending commands to other members.
      Parameters:
      restClient - the client used to reach other members
      executor - the executor the blocking HTTP exchanges run on
      properties - the connector's properties
      converterProvider - provides the MessageConverter, if one is available
      Returns:
      the dispatcher sending commands to other members
    • axoniqSpringCloudIncomingCommandInvoker

      @Bean @ConditionalOnMissingBean public IncomingCommandInvoker axoniqSpringCloudIncomingCommandInvoker(SpringCloudMemberDiscovery discovery, org.springframework.beans.factory.ObjectProvider<MessageConverter> converterProvider)
      Bean creation method for the IncomingCommandInvoker handling commands sent by other members.
      Parameters:
      discovery - the discovery naming this member in the failures the invoker reports
      converterProvider - provides the MessageConverter, if one is available
      Returns:
      the invoker handling commands sent by other members
    • axoniqSpringCloudCommandController

      @Bean @ConditionalOnMissingBean @ConditionalOnWebApplication(type=SERVLET) public SpringCloudCommandController axoniqSpringCloudCommandController(IncomingCommandInvoker invoker)
      Bean creation method for the controller receiving commands from other members.
      Parameters:
      invoker - the invoker handling commands sent by other members
      Returns:
      the controller receiving commands from other members
    • axoniqSpringCloudIncomingQueryInvoker

      @Bean @ConditionalOnMissingBean public IncomingQueryInvoker axoniqSpringCloudIncomingQueryInvoker(SpringCloudMemberDiscovery discovery, org.springframework.beans.factory.ObjectProvider<MessageConverter> converterProvider)
      Bean creation method for the IncomingQueryInvoker answering queries sent by other members.
      Parameters:
      discovery - the discovery naming this member in the failures the invoker reports
      converterProvider - provides the MessageConverter, if one is available
      Returns:
      the invoker answering queries sent by other members
    • axoniqSpringCloudShutdownLifecycle

      @Bean public org.springframework.context.SmartLifecycle axoniqSpringCloudShutdownLifecycle(org.springframework.beans.factory.ObjectProvider<AxonConfiguration> configuration, IncomingQueryInvoker invoker)
      Announces this member leaving on the subscription queries it answers, before the web server stops serving their streams.
      Parameters:
      configuration - provides the configuration holding the streaming event processors to stop first
      invoker - the invoker answering the subscriptions to announce this member leaving on
      Returns:
      the lifecycle announcing this member leaving on shutdown
    • axoniqSpringCloudRemoteQueryDispatcher

      @Bean @ConditionalOnMissingBean public RemoteQueryDispatcher axoniqSpringCloudRemoteQueryDispatcher(@Qualifier("axoniqSpringCloudQueryRestClient") org.springframework.web.client.RestClient restClient, @Qualifier("axoniqSpringCloudDispatchExecutor") Executor executor, @Qualifier("axoniqSpringCloudQueryScheduler") ScheduledExecutorService scheduler, MessageConverter converter, SpringCloudProperties properties)
      Bean creation method for the RemoteQueryDispatcher sending queries to other members.
      Parameters:
      restClient - the client sending the queries and subscription queries
      executor - the executor each query's response stream is read on
      scheduler - the scheduler each query's deadline runs on
      converter - the converter the events of a query's response stream are read with
      properties - the connector's properties
      Returns:
      the dispatcher sending queries to other members
    • axoniqSpringCloudQueryController

      @Bean @ConditionalOnMissingBean @ConditionalOnWebApplication(type=SERVLET) public SpringCloudQueryController axoniqSpringCloudQueryController(IncomingQueryInvoker invoker, @Qualifier("axoniqSpringCloudQueryScheduler") ScheduledExecutorService scheduler, @Qualifier("axoniqSpringCloudKeepAliveExecutor") Executor keepAliveExecutor, SpringCloudProperties properties)
      Bean creation method for the controller answering queries from other members.
      Parameters:
      invoker - the invoker answering queries sent by other members
      scheduler - the scheduler deciding when each open subscription is due a keep-alive
      keepAliveExecutor - the executor those keep-alives are written on
      properties - the connector's properties
      Returns:
      the controller answering queries from other members
    • axoniqSpringCloudKeepAliveExecutor

      @Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudKeepAliveExecutor") @ConditionalOnMissingBean(name="axoniqSpringCloudKeepAliveExecutor") @ConditionalOnWebApplication(type=SERVLET) public ExecutorService axoniqSpringCloudKeepAliveExecutor()
      Bean creation method for the Executor the keep-alive of each subscription being answered is written on.

      Separate from the scheduler that decides when a keep-alive is due, because writing one is a blocking write to a single subscriber and deciding it is due is not. A subscriber that has stopped reading without closing blocks its write until the connection gives way; were that the scheduler's thread, it would hold up every other subscription's keep-alive and every dispatched query's deadline with it.

      A virtual-thread-per-task executor, for the same reason the dispatch executor is one: the work is a blocking write and nothing else, and sizing a platform thread pool for it would cap the subscriptions this member can answer at the pool's own size.

      Returns:
      the executor subscription keep-alives are written on
    • axoniqSpringCloudMemberCapabilitiesController

      @Bean @ConditionalOnMissingBean @ConditionalOnWebApplication(type=SERVLET) public MemberCapabilitiesController axoniqSpringCloudMemberCapabilitiesController(CapabilityDiscoveryMode discoveryMode)
      Bean creation method for the controller serving this application's capabilities to other members.
      Parameters:
      discoveryMode - the mode holding this application's own capabilities
      Returns:
      the controller serving this application's capabilities