com.evento.application.EventoBundle Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of evento-bundle Show documentation
Show all versions of evento-bundle Show documentation
Evento Framework - Bundle. The library to build a RECQ System based on Evento Server
The newest version!
package com.evento.application;
import com.evento.application.consumer.EventConsumer;
import com.evento.application.manager.*;
import com.evento.application.performance.TracingAgent;
import com.evento.application.performance.Track;
import com.evento.common.modeling.messaging.message.internal.consumer.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.evento.application.bus.EventoServerClient;
import com.evento.application.bus.EventoServerMessageBusConfiguration;
import com.evento.application.proxy.GatewayTelemetryProxy;
import com.evento.application.proxy.InvokerWrapper;
import com.evento.common.documentation.Domain;
import com.evento.common.messaging.bus.EventoServer;
import com.evento.common.messaging.consumer.ConsumerStateStore;
import com.evento.common.messaging.consumer.impl.InMemoryConsumerStateStore;
import com.evento.common.messaging.gateway.CommandGateway;
import com.evento.common.messaging.gateway.CommandGatewayImpl;
import com.evento.common.messaging.gateway.QueryGateway;
import com.evento.common.messaging.gateway.QueryGatewayImpl;
import com.evento.common.modeling.annotations.handler.InvocationHandler;
import com.evento.common.modeling.annotations.handler.SagaEventHandler;
import com.evento.common.modeling.bundle.types.ComponentType;
import com.evento.common.modeling.bundle.types.HandlerType;
import com.evento.common.modeling.bundle.types.PayloadType;
import com.evento.common.modeling.messaging.message.application.*;
import com.evento.common.modeling.messaging.message.internal.discovery.BundleRegistration;
import com.evento.common.modeling.messaging.message.internal.discovery.RegisteredHandler;
import com.evento.common.modeling.messaging.payload.DomainEvent;
import com.evento.common.modeling.messaging.query.Multiple;
import com.evento.common.performance.AutoscalingProtocol;
import com.evento.common.performance.PerformanceService;
import com.evento.common.performance.RemotePerformanceService;
import com.evento.common.serialization.ObjectMapperUtils;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* The EventoBundle class represents a bundle of components and services related to event handling.
* It provides functionality for starting saga event consumers and projector event consumers.
*/
@Getter
public class EventoBundle {
private static final Logger logger = LogManager.getLogger(EventoBundle.class);
private final String basePackage;
private final String bundleId;
private final String instanceId;
private final PerformanceService performanceService;
private final AggregateManager aggregateManager;
private final ServiceManager serviceManager;
private final ProjectionManager projectionManager;
private final ProjectorManager projectorManager;
private final ObserverManager observerManager;
private final SagaManager sagaManager;
private final transient CommandGateway commandGateway;
private final transient QueryGateway queryGateway;
private final TracingAgent tracingAgent;
private EventoBundle(
String basePackage,
String bundleId,
String instanceId,
AggregateManager aggregateManager,
ProjectionManager projectionManager,
SagaManager sagaManager,
CommandGateway commandGateway,
QueryGateway queryGateway,
PerformanceService performanceService,
ServiceManager serviceManager, ProjectorManager projectorManager,
ObserverManager observerManager, TracingAgent tracingAgent
) {
this.basePackage = basePackage;
this.bundleId = bundleId;
this.instanceId = instanceId;
this.aggregateManager = aggregateManager;
this.projectionManager = projectionManager;
this.sagaManager = sagaManager;
this.performanceService = performanceService;
this.commandGateway = commandGateway;
this.queryGateway = queryGateway;
this.serviceManager = serviceManager;
this.projectorManager = projectorManager;
this.tracingAgent = tracingAgent;
this.observerManager = observerManager;
}
/**
* Creates a GatewayTelemetryProxy with the provided parameters.
*
* @param commandGateway The command gateway to proxy.
* @param queryGateway The query gateway to proxy.
* @param bundleId The bundle identifier.
* @param performanceService The performance service for tracking metrics.
* @param tracingAgent The tracing agent for correlating and tracking.
* @param componentName The name of the component associated with the proxy.
* @param handledMessage The message being handled by the proxy.
* @return The created GatewayTelemetryProxy instance.
*/
private static GatewayTelemetryProxy createGatewayTelemetryProxy(
CommandGateway commandGateway,
QueryGateway queryGateway,
String bundleId,
String instanceId,
PerformanceService performanceService,
TracingAgent tracingAgent,
String componentName, Message> handledMessage) {
return new GatewayTelemetryProxy(commandGateway, queryGateway, bundleId, performanceService,
componentName, handledMessage, tracingAgent, instanceId);
}
/**
* Retrieves an instance of the specified InvokerWrapper class.
*
* @param invokerClass The class of the InvokerWrapper to retrieve.
* @param The type of the InvokerWrapper.
* @return An instance of the specified InvokerWrapper class.
* @throws RuntimeException if an error occurs while creating the instance.
*/
@SuppressWarnings("unchecked")
public T getInvoker(Class invokerClass) {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(invokerClass);
var h = new MethodHandler() {
@Override
public Object invoke(Object self, Method method, Method proceed, Object[] args) throws Exception {
if (method.getDeclaredAnnotation(InvocationHandler.class) != null) {
var payload = new InvocationMessage(
invokerClass, method, args
);
var gProxy = createGatewayTelemetryProxy(
commandGateway,
queryGateway,
bundleId, instanceId,
performanceService,
tracingAgent,
invokerClass.getSimpleName(),
payload
);
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(invokerClass);
var target = factory.create(new Class>[0], new Object[]{},
(s, m, p, a) -> {
if (m.getName().equals("getCommandGateway")) {
return gProxy;
}
if (m.getName().equals("getQueryGateway")) {
return gProxy;
}
return p.invoke(s, a);
});
var start = Instant.now();
return tracingAgent.track(payload, invokerClass.getSimpleName(),
method.getDeclaredAnnotation(Track.class),
() -> {
Object result;
try{
result = proceed.invoke(target, args);
}catch (Exception e){
gProxy.sendServiceTimeMetric(start);
throw e;
}
if(result instanceof CompletableFuture> cf){
result = cf.whenComplete((s,f) -> gProxy.sendServiceTimeMetric(start));
}else{
gProxy.sendServiceTimeMetric(start);
}
return result;
});
}
return proceed.invoke(self, args);
}
};
try {
return (T) factory.create(new Class>[0], new Object[]{}, h);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* Retrieves information about the application.
*
* @return An instance of the ApplicationInfo class containing the following information:
* - basePackage: The base package of the application.
* - bundleId: The bundle identifier of the application.
* - aggregateMessageHandlers: The set of aggregate message handlers in the application.
* - serviceMessageHandlers: The set of service message handlers in the application.
* - projectionMessageHandlers: The set of projection message handlers in the application.
* - projectorMessageHandlers: The set of projector message handlers in the application.
* - sagaMessageHandlers: The set of saga message handlers in the application.
*/
public ApplicationInfo getAppInfo() {
var info = new ApplicationInfo();
info.basePackage = basePackage;
info.bundleId = bundleId;
info.aggregateMessageHandlers = aggregateManager.getHandlers().keySet();
info.serviceMessageHandlers = serviceManager.getHandlers().keySet();
info.projectionMessageHandlers = projectionManager.getHandlers().keySet();
info.projectorMessageHandlers = projectorManager.getHandlers().keySet();
info.sagaMessageHandlers = sagaManager.getHandlers().keySet();
return info;
}
/**
* Represents information about an application.
*/
public static class ApplicationInfo {
/**
* Represents the base package that is used for scanning components in an application.
*/
public String basePackage;
/**
* Represents the bundle identifier of an application.
*/
public String bundleId;
/**
* Represents a set of aggregate message handlers.
*/
public Set aggregateMessageHandlers;
/**
* The set of service message handlers.
*/
public Set serviceMessageHandlers;
/**
* Represents a set of projection message handlers.
*/
public Set projectionMessageHandlers;
/**
* A set of available message handlers for the projector.
*/
public Set projectorMessageHandlers;
/**
* A set of string values representing the saga message handlers.
*
*/
public Set sagaMessageHandlers;
}
/**
* The Builder class is responsible for constructing an EventoBundle and starting the Evento application.
*/
@Getter
@Setter
@Accessors(chain = true)
public static class Builder {
private Package basePackage;
private String bundleId;
private String instanceId;
private long bundleVersion = 1;
private Function, Object> injector;
private Function autoscalingProtocolBuilder;
private BiFunction consumerStateStoreBuilder;
private Function commandGatewayBuilder = CommandGatewayImpl::new;
@Setter(AccessLevel.NONE)
private CommandGateway commandGateway;
private Function queryGatewayBuilder = QueryGatewayImpl::new;
@Setter(AccessLevel.NONE)
private QueryGateway queryGateway;
private Function performanceServiceBuilder = eventoServer -> new RemotePerformanceService(eventoServer, 1);
@Setter(AccessLevel.NONE)
private PerformanceService performanceService;
private int sssFetchSize = 1000;
private int sssFetchDelay = 1000;
private TracingAgent tracingAgent;
private EventoServerMessageBusConfiguration eventoServerMessageBusConfiguration;
private ObjectMapper objectMapper = ObjectMapperUtils.getPayloadObjectMapper();
private Map> contexts = new HashMap<>();
private Consumer onEventoStartedHook = (eventoServer) -> {};
/**
* The Builder class represents a builder for constructing objects.
*/
private Builder() {
}
/**
* Returns a new instance of the Builder class.
*
* @return a new instance of the Builder class
*/
public static Builder builder() {
return new Builder();
}
/**
* Starts the Evento Application.
*
* @return the EventoBundle representing the started application
* @throws Exception if there is an error during initialization
*/
public EventoBundle start() throws Exception {
if (basePackage == null) {
throw new IllegalArgumentException("Invalid basePackage");
}
if (bundleId == null || bundleId.isBlank() || bundleId.isEmpty()) {
throw new IllegalArgumentException("Invalid bundleId");
}
if (eventoServerMessageBusConfiguration == null) {
throw new IllegalArgumentException("Invalid messageBusConfiguration");
}
if (injector == null) {
injector = clz -> null;
}
if (instanceId == null || instanceId.isBlank() || instanceId.isEmpty()) {
instanceId = UUID.randomUUID().toString();
}
if (sssFetchSize < 1) {
sssFetchSize = 1;
}
if (sssFetchDelay < 100) {
sssFetchDelay = 100;
}
if (tracingAgent == null) {
tracingAgent = new TracingAgent(bundleId, bundleVersion);
}
var isShuttingDown = new AtomicBoolean();
var aggregateManager = new AggregateManager(
bundleId,
(c, p) -> createGatewayTelemetryProxy(commandGateway, queryGateway, bundleId, instanceId, performanceService,
tracingAgent, c, p),
tracingAgent
);
var serviceManager = new ServiceManager(
bundleId,
(c, p) -> createGatewayTelemetryProxy(commandGateway, queryGateway, bundleId, instanceId, performanceService,
tracingAgent, c, p),
tracingAgent
);
var projectionManager = new ProjectionManager(
bundleId,
(c, p) -> createGatewayTelemetryProxy(commandGateway, queryGateway, bundleId, instanceId, performanceService,
tracingAgent, c, p),
tracingAgent
);
var projectorManager = new ProjectorManager(
bundleId,
(c, p) -> createGatewayTelemetryProxy(commandGateway, queryGateway, bundleId, instanceId, performanceService,
tracingAgent, c, p),
tracingAgent,
isShuttingDown::get,
sssFetchSize,
sssFetchDelay
);
var sagaManager = new SagaManager(
bundleId,
(c, p) -> createGatewayTelemetryProxy(commandGateway, queryGateway, bundleId, instanceId, performanceService,
tracingAgent, c, p),
tracingAgent,
isShuttingDown::get,
sssFetchSize,
sssFetchDelay
);
var observerManager = new ObserverManager(
bundleId,
(c, p) -> createGatewayTelemetryProxy(commandGateway, queryGateway, bundleId, instanceId, performanceService,
tracingAgent, c, p),
tracingAgent,
isShuttingDown::get,
sssFetchSize,
sssFetchDelay
);
var invokerManager = new InvokerManager();
logger.info("Discovery handlers in %s".formatted(basePackage));
Reflections reflections = new Reflections((new ConfigurationBuilder().forPackages(basePackage.getName())));
aggregateManager.parse(reflections, injector);
serviceManager.parse(reflections, injector);
projectionManager.parse(reflections, injector);
projectorManager.parse(reflections, injector);
sagaManager.parse(reflections, injector);
observerManager.parse(reflections, injector);
invokerManager.parse(reflections);
logger.info("Discovery Complete");
var handlers = new ArrayList();
var payloads = new HashSet>();
aggregateManager.getHandlers().forEach((k, v) -> {
var r = v.getAggregateCommandHandler(k).getReturnType().getSimpleName();
handlers.add(new RegisteredHandler(
ComponentType.Aggregate,
v.getRef().getClass().getSimpleName(),
HandlerType.AggregateCommandHandler,
PayloadType.DomainCommand,
k,
r,
false,
null
));
var esh = v.getEventSourcingHandler(r);
if (esh != null) {
handlers.add(new RegisteredHandler(
ComponentType.Aggregate,
v.getRef().getClass().getSimpleName(),
HandlerType.EventSourcingHandler,
PayloadType.DomainEvent,
r,
null,
false,
null
));
}
payloads.add(v.getAggregateCommandHandler(k).getParameterTypes()[0]);
payloads.add(v.getAggregateCommandHandler(k).getReturnType());
});
serviceManager.getHandlers().forEach((k, v) -> {
var r = v.getAggregateCommandHandler(k).getReturnType().getSimpleName();
handlers.add(new RegisteredHandler(
ComponentType.Service,
v.getRef().getClass().getSimpleName(),
HandlerType.CommandHandler,
PayloadType.ServiceCommand,
k,
r.equals("void") ? null : r,
false,
null
));
payloads.add(v.getAggregateCommandHandler(k).getParameterTypes()[0]);
payloads.add(v.getAggregateCommandHandler(k).getReturnType());
});
projectorManager.getHandlers().forEach((k, v) -> v.forEach((k1, v1) -> {
handlers.add(new RegisteredHandler(
ComponentType.Projector,
v1.getRef().getClass().getSimpleName(),
HandlerType.EventHandler,
v1.getEventHandler(k).getParameterTypes()[0].getSuperclass().isAssignableFrom(DomainEvent.class) ? PayloadType.DomainEvent : PayloadType.ServiceEvent,
k,
null,
false,
null
));
payloads.add(v1.getEventHandler(k).getParameterTypes()[0]);
}));
observerManager.getHandlers().forEach((k, v) -> v.forEach((k1, v1) -> {
handlers.add(new RegisteredHandler(
ComponentType.Observer,
v1.getRef().getClass().getSimpleName(),
HandlerType.EventHandler,
v1.getEventHandler(k).getParameterTypes()[0].getSuperclass().isAssignableFrom(DomainEvent.class) ? PayloadType.DomainEvent : PayloadType.ServiceEvent,
k,
null,
false,
null
));
payloads.add(v1.getEventHandler(k).getParameterTypes()[0]);
}));
sagaManager.getHandlers().forEach((k, v) -> v.forEach((k1, v1) -> {
handlers.add(new RegisteredHandler(
ComponentType.Saga,
v1.getRef().getClass().getSimpleName(),
HandlerType.SagaEventHandler,
v1.getSagaEventHandler(k).getParameterTypes()[0].getSuperclass().isAssignableFrom(DomainEvent.class) ? PayloadType.DomainEvent : PayloadType.ServiceEvent,
k,
null,
false,
v1.getSagaEventHandler(k).getAnnotation(SagaEventHandler.class).associationProperty()
));
payloads.add(v1.getSagaEventHandler(k).getParameterTypes()[0]);
}));
projectionManager.getHandlers().forEach((k, v) -> {
var r = v.getQueryHandler(k).getReturnType();
handlers.add(new RegisteredHandler(
ComponentType.Projection,
v.getRef().getClass().getSimpleName(),
HandlerType.QueryHandler,
PayloadType.Query,
k,
((Class>) (((ParameterizedType) v.getQueryHandler(k).getGenericReturnType()).getActualTypeArguments()[0])).getSimpleName(),
r.isAssignableFrom(Multiple.class),
null
));
payloads.add(v.getQueryHandler(k).getParameterTypes()[0]);
payloads.add(((Class>) ((ParameterizedType) v.getQueryHandler(k).getGenericReturnType()).getActualTypeArguments()[0]));
});
handlers.addAll(invokerManager.getHandlers());
ObjectMapper mapper = new ObjectMapper();
JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
var payloadInfo = new HashMap();
for (Class> p : payloads) {
if (p == null) continue;
var info = new String[2];
payloadInfo.put(p.getSimpleName(), info);
try {
info[0] = mapper.writeValueAsString(schemaGen.generateSchema(p));
} catch (Exception ignored) {
}
if (p.getAnnotation(Domain.class) != null) {
info[1] = p.getAnnotation(Domain.class).name();
}
}
var registration = new BundleRegistration(
bundleId,
bundleVersion,
instanceId,
handlers,
payloadInfo
);
final AtomicReference eventoBundle = new AtomicReference<>();
logger.info("Starting EventoApplication %s".formatted(bundleId));
logger.info("Connecting to Evento Server...");
var eventoServer =
new EventoServerClient.Builder(
registration,
objectMapper,
eventoServerMessageBusConfiguration.getAddresses(),
(body) -> switch (body) {
case DecoratedDomainCommandMessage cm -> aggregateManager.handle(cm);
case ServiceCommandMessage sm -> serviceManager.handle(sm);
case QueryMessage> qm -> projectionManager.handle(qm);
case ConsumerFetchStatusRequestMessage cr -> {
var resp = new ConsumerFetchStatusResponseMessage();
eventoBundle.get()
.getEventConsumer(cr.getConsumerId(), cr.getComponentType())
.ifPresent(c -> {
try {
resp.setDeadEvents(c.getDeadEventQueue());
resp.setLastEventSequenceNumber(c.getLastConsumedEvent());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
yield resp;
}
case ConsumerSetEventRetryRequestMessage cr -> {
var resp = new ConsumerResponseMessage();
resp.setSuccess(true);
eventoBundle.get()
.getEventConsumer(cr.getConsumerId(), cr.getComponentType())
.ifPresent(c -> {
try {
c.setDeadEventRetry(cr.getEventSequenceNumber(), cr.isRetry());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
yield resp;
}
case ConsumerProcessDeadQueueRequestMessage cr -> {
var resp = new ConsumerResponseMessage();
resp.setSuccess(true);
eventoBundle.get()
.getEventConsumer(cr.getConsumerId(), cr.getComponentType())
.ifPresent(c -> {
try {
c.consumeDeadEventQueue();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
yield resp;
}
case ConsumerDeleteDeadEventRequestMessage cr -> {
var resp = new ConsumerResponseMessage();
resp.setSuccess(true);
eventoBundle.get()
.getEventConsumer(cr.getConsumerId(), cr.getComponentType())
.ifPresent(c -> {
try {
c.deleteDeadEvent(cr.getEventSequenceNumber());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
yield resp;
}
case null, default -> throw new RuntimeException("Invalid request body: " + body);
}
)
.setMaxReconnectAttempts(eventoServerMessageBusConfiguration.getMaxReconnectAttempts())
.setReconnectDelayMillis(eventoServerMessageBusConfiguration.getReconnectDelayMillis())
.setMaxDisableAttempts(eventoServerMessageBusConfiguration.getMaxDisableAttempts())
.setDisableDelayMillis(eventoServerMessageBusConfiguration.getDisableDelayMillis())
.setMaxRetryAttempts(eventoServerMessageBusConfiguration.getMaxRetryAttempts())
.setRetryDelayMillis(eventoServerMessageBusConfiguration.getRetryDelayMillis())
.connect();
if(autoscalingProtocolBuilder == null){
autoscalingProtocolBuilder = (e) -> new AutoscalingProtocol(e) {
@Override
public void arrival() {
}
@Override
public void departure() {
}
};
}
var autoscalingProtocol = autoscalingProtocolBuilder.apply(eventoServer);
logger.info("Autoscaling protocol: %s".formatted(autoscalingProtocol.getClass().getName()));
tracingAgent.setAutoscalingProtocol(autoscalingProtocol);
if (consumerStateStoreBuilder == null) {
consumerStateStoreBuilder = InMemoryConsumerStateStore::new;
}
if (commandGateway == null) {
commandGateway = commandGatewayBuilder.apply(eventoServer);
}
if (queryGateway == null) {
queryGateway = queryGatewayBuilder.apply(eventoServer);
}
if(performanceService == null) {
performanceService = performanceServiceBuilder.apply(eventoServer);
}
var css = consumerStateStoreBuilder.apply(eventoServer, performanceService);
eventoBundle.set(new EventoBundle(
basePackage.getName(),
bundleId, instanceId,
aggregateManager, projectionManager, sagaManager, commandGateway,
queryGateway,
performanceService,
serviceManager, projectorManager, observerManager, tracingAgent));
logger.info("Starting projector consumers...");
var start = Instant.now();
var wait = new Semaphore(0);
eventoBundle.get().startProjectorEventConsumers(wait::release, css, contexts);
var startThread = new Thread(() -> {
try {
wait.acquire();
logger.info("All Projector Consumers head Reached! (in {} millis)", Instant.now().toEpochMilli() - start.toEpochMilli());
logger.info("Sending registration to enable the Bundle");
eventoServer.enable();
eventoBundle.get().startSagaEventConsumers(css, contexts);
eventoBundle.get().startObserverEventConsumers(css, contexts);
eventoServer.registerConsumers(eventoBundle.get());
logger.info("Application Started!");
Thread.startVirtualThread(() -> onEventoStartedHook.accept(eventoBundle.get()));
}catch (Exception e){
logger.error("Error during startup", e);
System.exit(1);
}
});
startThread.setName("Start Bundle Thread");
startThread.start();
return eventoBundle.get();
}
}
private Optional extends EventConsumer> getEventConsumer(String consumerId, ComponentType componentType) {
return switch (componentType){
case Saga ->
getSagaManager().getSagaEventConsumers()
.stream().filter(c -> c.getConsumerId().equals(consumerId))
.findFirst();
case Projector -> getProjectorManager().getProjectorEvenConsumers()
.stream().filter(c -> c.getConsumerId().equals(consumerId))
.findFirst();
case Observer -> getObserverManager().getObserverEventConsumers()
.stream().filter(c -> c.getConsumerId().equals(consumerId))
.findFirst();
case null, default -> throw new RuntimeException("Invalid consumer fetch " + consumerId + " - " + componentType);
};
}
/**
* Starts the saga event consumers for the registered SagaReferences. Each SagaReference is checked for
* the Saga annotation, and for each context specified in the annotation, a new SagaEventConsumer is created
* and started in a new thread.
*
* @param consumerStateStore the consumer state store to track the state of event consumers
* @param contexts the component contexts associations
*/
private void startSagaEventConsumers(ConsumerStateStore consumerStateStore, Map> contexts) {
sagaManager.startSagaEventConsumers(consumerStateStore, contexts);
}
/**
* Starts the projector event consumers for the specified contexts.
*
* @param onAllHeadReached The callback to be executed when all heads are reached.
* @param consumerStateStore The consumer state store to track the state of event consumers.
* @param contexts The contexts for which the projector event consumers should be started.
*/
private void startProjectorEventConsumers(Runnable onAllHeadReached, ConsumerStateStore consumerStateStore, Map> contexts) {
projectorManager.startEventConsumers(onAllHeadReached, consumerStateStore, contexts);
}
/**
* Starts the observer event consumers for the registered ObserverReferences. Each ObserverReference is checked for
* the Observer annotation, and for each context specified in the annotation, a new ObserverEventConsumer is created
* and started in a new thread.
*
* @param consumerStateStore The consumer state store to track the state of event consumers.
* @param contexts the component contexts associations
*/
private void startObserverEventConsumers(ConsumerStateStore consumerStateStore, Map> contexts) {
observerManager.startEventConsumers(consumerStateStore, contexts);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy