com.evento.application.consumer.ProjectorEvenConsumer 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.consumer;
import com.evento.application.performance.TracingAgent;
import com.evento.application.reference.ProjectorReference;
import lombok.Getter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.evento.application.proxy.GatewayTelemetryProxy;
import com.evento.common.messaging.consumer.ConsumerStateStore;
import com.evento.common.modeling.messaging.message.application.Message;
import com.evento.common.utils.ProjectorStatus;
import com.evento.common.utils.Sleep;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Supplier;
/**
* Represents a consumer for projector events, responsible for processing and handling events
* in a projector context.
*/
public class ProjectorEvenConsumer extends EventConsumer {
private static final Logger logger = LogManager.getLogger(ProjectorEvenConsumer.class);
// Fields for configuration and dependencies
@Getter
private final String bundleId;
@Getter
private final String projectorName;
@Getter
private final int projectorVersion;
@Getter
private final String context;
private final Supplier isShuttingDown;
private final HashMap> projectorMessageHandlers;
private final TracingAgent tracingAgent;
private final BiFunction, GatewayTelemetryProxy> gatewayTelemetryProxy;
@Getter
private final int sssFetchSize;
@Getter
private final int sssFetchDelay;
private final AtomicInteger alignmentCounter;
private final Runnable onAllHeadReached;
/**
* Constructs a new ProjectorEvenConsumer with the specified parameters.
*
* @param bundleId The bundle identifier.
* @param projectorName The name of the projector.
* @param projectorVersion The version of the projector.
* @param context The context in which the projector operates.
* @param isShuttingDown A supplier indicating whether the consumer is shutting down.
* @param consumerStateStore The state store for tracking consumer state.
* @param projectorMessageHandlers The map of event names to projector handlers.
* @param tracingAgent The tracing agent for tracking events.
* @param gatewayTelemetryProxy The function for creating a telemetry proxy for a gateway.
* @param sssFetchSize The fetch size for consuming events from the state store.
* @param sssFetchDelay The delay for fetching events from the state store.
* @param alignmentCounter The atomic counter for tracking alignment.
* @param onAllHeadReached The runnable to execute when the head is reached.
*/
public ProjectorEvenConsumer(String bundleId,
String projectorName, int projectorVersion,
String context, Supplier isShuttingDown,
ConsumerStateStore consumerStateStore,
HashMap> projectorMessageHandlers,
TracingAgent tracingAgent, BiFunction,
GatewayTelemetryProxy> gatewayTelemetryProxy, int sssFetchSize,
int sssFetchDelay, AtomicInteger alignmentCounter,
Runnable onAllHeadReached) {
super(bundleId + "_" + projectorName + "_" + projectorVersion + "_" + context, consumerStateStore);
// Initialization of fields
this.bundleId = bundleId;
this.projectorName = projectorName;
this.projectorVersion = projectorVersion;
this.context = context;
this.isShuttingDown = isShuttingDown;
this.projectorMessageHandlers = projectorMessageHandlers;
this.tracingAgent = tracingAgent;
this.gatewayTelemetryProxy = gatewayTelemetryProxy;
this.sssFetchSize = sssFetchSize;
this.sssFetchDelay = sssFetchDelay;
this.alignmentCounter = alignmentCounter;
this.onAllHeadReached = onAllHeadReached;
}
/**
* Runs the projector event consumer, continuously processing and handling events
* until the shutdown condition is met.
*/
@Override
public void run() {
// Initialize projector status
var ps = new ProjectorStatus();
ps.setHeadReached(false);
// Main loop for event processing
while (!isShuttingDown.get()) {
var hasError = false;
var consumedEventCount = 0;
try {
// Consume events from the state store and process them
consumedEventCount = consumerStateStore.consumeEventsForProjector(
consumerId,
projectorName,
context,
publishedEvent -> {
// Retrieve handlers for the event name
var handlers = projectorMessageHandlers
.get(publishedEvent.getEventName());
if (handlers == null) return;
// Retrieve the handler for the current projector
var handler = handlers.getOrDefault(projectorName, null);
if (handler == null) return;
// Create telemetry proxy for the gateway
var proxy = gatewayTelemetryProxy.apply(handler.getComponentName(),
publishedEvent.getEventMessage());
// Track the event using the tracing agent
tracingAgent.track(publishedEvent.getEventMessage(), handler.getComponentName(),
null,
() -> {
// Invoke the handler and send telemetry metrics
handler.invoke(
publishedEvent,
proxy,
proxy,
ps
);
proxy.sendInvocationsMetric();
return null;
});
}, sssFetchSize);
} catch (Throwable e) {
logger.error("Error on projector consumer: " + consumerId, e);
hasError = true;
}
// Sleep based on fetch size and error conditions
if (sssFetchSize - consumedEventCount > 10) {
Sleep.apply(hasError ? sssFetchDelay : sssFetchSize - consumedEventCount);
}
// Check for head reached condition and execute onHeadReached if necessary
if (!hasError && !ps.isHeadReached() && consumedEventCount >= 0 && consumedEventCount < sssFetchSize) {
ps.setHeadReached(true);
logger.info("Event consumer head Reached for Projector: %s - Version: %d - Context: %s"
.formatted(projectorName, projectorVersion, context));
var aligned = alignmentCounter.decrementAndGet();
if (aligned == 0) {
onAllHeadReached.run();
}
}
}
}
public void consumeDeadEventQueue() throws Exception {
// Initialize projector status
var ps = new ProjectorStatus();
ps.setHeadReached(true);
consumerStateStore.consumeDeadEventsForProjector(
consumerId,
projectorName,
publishedEvent -> {
// Retrieve handlers for the event name
var handlers = projectorMessageHandlers
.get(publishedEvent.getEventName());
if (handlers == null) return;
// Retrieve the handler for the current projector
var handler = handlers.getOrDefault(projectorName, null);
if (handler == null) return;
// Create telemetry proxy for the gateway
var proxy = gatewayTelemetryProxy.apply(handler.getComponentName(),
publishedEvent.getEventMessage());
// Track the event using the tracing agent
tracingAgent.track(publishedEvent.getEventMessage(), handler.getComponentName(),
null,
() -> {
// Invoke the handler and send telemetry metrics
handler.invoke(
publishedEvent,
proxy,
proxy,
ps
);
proxy.sendInvocationsMetric();
return null;
});
}
);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy