Class MultiTenantStreamingProcessorRestarter
- All Implemented Interfaces:
DescribableComponent
StreamingEventProcessors whenever the set of tenants changes, so
a processor streaming across tenants re-opens its stream with the current tenants.
A running stream cannot change its set of tenants. The merged stream is assembled over the tenants present when it opened, so a tenant added afterwards is not read and a removed tenant's stream stays open. Re-opening the stream with the current tenants requires a processor restart, which the coordinator supports.
The restart follows the MultiTenantEventStorageEngine handed to
follow(MultiTenantEventStorageEngine) at startup, rather than the
TenantProvider that engine itself follows. A
tenant change reaches the provider's subscribers in turn, and a subscriber ahead of the engine may take real time
over its own registration, such as one opening a connection for the tenant. A restart takes barely any time by
comparison, so a restart driven by the provider can re-open the stream while the engine still reports the previous
tenants. The new tenant is then missing from a stream that nothing re-opens again, because no further tenant change
follows. Following the engine rules that out: it announces a change only once that change is visible through its own
tenants.
Restarts are coalesced onto a single thread: a burst of tenant changes, such as the initial discovery of several tenants, results in as few restarts as possible while still ending on the current tenant set. Every restart pauses processing for all tenants briefly. Whether the tenants discovered at startup request a restart depends on whether this restarter subscribed before they were registered, which is not fixed. Either way the processors start far later in the lifecycle, so such a request finds nothing running and each processor opens its stream over the full startup set of its own accord.
Every running streaming event processor is restarted, not only the ones consuming across tenants. With the module on the classpath multi-tenancy is on by default, so the event store routes across tenants and a pooled streaming processor consumes them all. Restarting a processor that reads another source is harmless. It re-opens its own source. Restarting only the multi-tenant processors would require inspecting each processor's configured source, which the processor API does not expose, and tenant changes are infrequent, so restarting all of them is the simpler and safe choice.
Each processor's shutdown-and-start is bounded by a safety-net timeout, so a processor that never completes its
shutdown or start cannot block the restart thread. It is taken from the
MultiTenantStreamingProcessorRestartConfiguration, which defaults to 30 seconds. A deployment whose
processors are slow to stop and start can register a customized
MultiTenantStreamingProcessorRestartConfiguration to raise it.
Internal, because it is registered by the MultiTenancyConfigurationDefaults enhancer. The only member an
enhancer building a tenant-routing engine calls is follow(MultiTenantEventStorageEngine).
- Since:
- 5.3.0
- Author:
- Laura Devriendt
-
Method Summary
Modifier and TypeMethodDescriptionvoiddescribeTo(ComponentDescriptor descriptor) Describe the properties ofthis DescribableComponentwith the givendescriptor.voidfollow(MultiTenantEventStorageEngine engine) Follows the tenant changes of the givenengine, whose tenants decide what a re-opened stream spans.
-
Method Details
-
follow
Follows the tenant changes of the givenengine, whose tenants decide what a re-opened stream spans.Must be called with the engine an enhancer built, from a start handler on that engine's own component definition, rather than with one resolved from the
Configuration. The engine is registered underEventStorageEngineand any enhancer may decorate that type, so a resolved instance can be a decorator, which announces no tenant change at all.May be called before or after
start(), since a change announced while this restarter is not running is ignored. Only one engine can be followed, since a second one's tenants decide nothing about the merged stream the first one spans.- Parameters:
engine- the engine whose tenant changes re-open the streams of the running streaming event processors- Throws:
NullPointerException- if the givenengineisnullAxonConfigurationException- ifthisrestarter already follows an engine
-
describeTo
Description copied from interface:DescribableComponentDescribe the properties ofthis DescribableComponentwith the givendescriptor.Components should call the appropriate
describePropertymethods on the descriptor to register their properties. The descriptor is responsible for determining how these properties are formatted and structured in the final output.Best Practices: As a general rule, all relevant fields of a
DescribableComponentimplementation should be described in this method. However, developers have discretion to include only the fields that make sense in the context. Not every field may be meaningful for description purposes, especially internal implementation details. Furthermore, components might want to expose different information based on their current state. The final decision on what properties to include lies with the person implementing thedescribeTomethod, who should focus on providing information that is useful for understanding the component's configuration and state.Example implementation:
public void describeTo(ComponentDescriptor descriptor) { descriptor.describeProperty("name", this.name); descriptor.describeProperty("enabled", this.enabled); descriptor.describeProperty("configuration", this.configuration); // A nested component descriptor.describeProperty("handlers", this.eventHandlers); // A collection }- Specified by:
describeToin interfaceDescribableComponent- Parameters:
descriptor- The component descriptor to describethis DescribableComponentn its properties in.
-