org.enodeframework.messaging.impl.DefaultMessageDispatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of enode Show documentation
Show all versions of enode Show documentation
The enodeframework core implementation.
package org.enodeframework.messaging.impl;
import com.google.common.collect.Lists;
import org.enodeframework.common.function.Action2;
import org.enodeframework.common.function.Action4;
import org.enodeframework.common.io.IOHelper;
import org.enodeframework.infrastructure.IObjectProxy;
import org.enodeframework.infrastructure.ITypeNameProvider;
import org.enodeframework.messaging.IMessage;
import org.enodeframework.messaging.IMessageDispatcher;
import org.enodeframework.messaging.IMessageHandlerProvider;
import org.enodeframework.messaging.IMessageHandlerProxy1;
import org.enodeframework.messaging.IMessageHandlerProxy2;
import org.enodeframework.messaging.IMessageHandlerProxy3;
import org.enodeframework.messaging.IThreeMessageHandlerProvider;
import org.enodeframework.messaging.ITwoMessageHandlerProvider;
import org.enodeframework.messaging.MessageHandlerData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
/**
* @author [email protected]
*/
public class DefaultMessageDispatcher implements IMessageDispatcher {
private static final Logger logger = LoggerFactory.getLogger(DefaultMessageDispatcher.class);
private final ITypeNameProvider typeNameProvider;
private final IMessageHandlerProvider messageHandlerProvider;
private final ITwoMessageHandlerProvider twoMessageHandlerProvider;
private final IThreeMessageHandlerProvider threeMessageHandlerProvider;
public DefaultMessageDispatcher(ITypeNameProvider typeNameProvider, IMessageHandlerProvider messageHandlerProvider, ITwoMessageHandlerProvider twoMessageHandlerProvider, IThreeMessageHandlerProvider threeMessageHandlerProvider) {
this.typeNameProvider = typeNameProvider;
this.messageHandlerProvider = messageHandlerProvider;
this.twoMessageHandlerProvider = twoMessageHandlerProvider;
this.threeMessageHandlerProvider = threeMessageHandlerProvider;
}
@Override
public CompletableFuture dispatchMessageAsync(IMessage message) {
return dispatchMessages(Lists.newArrayList(message));
}
@Override
public CompletableFuture dispatchMessagesAsync(List extends IMessage> messages) {
return dispatchMessages(messages);
}
private CompletableFuture dispatchMessages(List extends IMessage> messages) {
int messageCount = messages.size();
if (messageCount == 0) {
return CompletableFuture.completedFuture(null);
}
RootDispatching rootDispatching = new RootDispatching();
//先对每个事件调用其Handler
QueueMessageDispatching queueMessageDispatching = new QueueMessageDispatching(this, rootDispatching, messages);
dispatchSingleMessage(queueMessageDispatching.dequeueMessage(), queueMessageDispatching);
//如果有至少两个事件,则尝试调用针对两个事件的Handler
if (messageCount >= 2) {
List> twoMessageHandlers = twoMessageHandlerProvider.getHandlers(messages.stream().map(x -> x.getClass()).collect(Collectors.toList()));
if (!twoMessageHandlers.isEmpty()) {
dispatchMultiMessage(messages, twoMessageHandlers, rootDispatching, this::dispatchTwoMessageToHandlerAsync);
}
}
//如果有至少三个事件,则尝试调用针对三个事件的Handler
if (messageCount >= 3) {
List> threeMessageHandlers = threeMessageHandlerProvider.getHandlers(messages.stream().map(x -> x.getClass()).collect(Collectors.toList()));
if (!threeMessageHandlers.isEmpty()) {
dispatchMultiMessage(messages, threeMessageHandlers, rootDispatching, this::dispatchThreeMessageToHandlerAsync);
}
}
return rootDispatching.getTaskCompletionSource();
}
private void dispatchSingleMessage(IMessage message, QueueMessageDispatching queueMessageDispatching) {
List> messageHandlerDataList = messageHandlerProvider.getHandlers(message.getClass());
if (messageHandlerDataList.isEmpty()) {
queueMessageDispatching.onMessageHandled(message);
return;
}
messageHandlerDataList.forEach(messageHandlerData -> {
SingleMessageDispatching singleMessageDispatching = new SingleMessageDispatching(message, queueMessageDispatching, messageHandlerData.allHandlers, typeNameProvider);
if (messageHandlerData.listHandlers != null && !messageHandlerData.listHandlers.isEmpty()) {
messageHandlerData.listHandlers.forEach(handler -> dispatchSingleMessageToHandlerAsync(singleMessageDispatching, handler, null, 0));
}
if (messageHandlerData.queuedHandlers != null && !messageHandlerData.queuedHandlers.isEmpty()) {
QueuedHandler queueHandler = new QueuedHandler<>(messageHandlerData.queuedHandlers, (queuedHandler, nextHandler) -> dispatchSingleMessageToHandlerAsync(singleMessageDispatching, nextHandler, queuedHandler, 0));
dispatchSingleMessageToHandlerAsync(singleMessageDispatching, queueHandler.dequeueHandler(), queueHandler, 0);
}
});
}
private void dispatchMultiMessage(List extends IMessage> messages, List> messageHandlerDataList, RootDispatching rootDispatching, Action4, Integer> dispatchAction) {
messageHandlerDataList.forEach(messageHandlerData -> {
MultiMessageDisptaching multiMessageDispatching = new MultiMessageDisptaching(messages, messageHandlerData.allHandlers, rootDispatching, typeNameProvider);
if (messageHandlerData.listHandlers != null && !messageHandlerData.listHandlers.isEmpty()) {
messageHandlerData.listHandlers.forEach(handler -> {
dispatchAction.apply(multiMessageDispatching, handler, null, 0);
});
}
if (messageHandlerData.queuedHandlers != null && !messageHandlerData.queuedHandlers.isEmpty()) {
QueuedHandler queuedHandler = new QueuedHandler<>(messageHandlerData.queuedHandlers, (currentQueuedHandler, nextHandler) ->
dispatchAction.apply(multiMessageDispatching, nextHandler, currentQueuedHandler, 0)
);
dispatchAction.apply(multiMessageDispatching, queuedHandler.dequeueHandler(), queuedHandler, 0);
}
});
}
private void dispatchSingleMessageToHandlerAsync(SingleMessageDispatching singleMessageDispatching, IMessageHandlerProxy1 handlerProxy, QueuedHandler queueHandler, int retryTimes) {
IMessage message = singleMessageDispatching.getMessage();
String messageTypeName = typeNameProvider.getTypeName(message.getClass());
Class> handlerType = handlerProxy.getInnerObject().getClass();
String handlerTypeName = typeNameProvider.getTypeName(handlerType);
handleSingleMessageAsync(singleMessageDispatching, handlerProxy, handlerTypeName, messageTypeName, queueHandler, retryTimes);
}
private void dispatchTwoMessageToHandlerAsync(MultiMessageDisptaching multiMessageDispatching, IMessageHandlerProxy2 handlerProxy, QueuedHandler queueHandler, int retryTimes) {
Class> handlerType = handlerProxy.getInnerObject().getClass();
String handlerTypeName = typeNameProvider.getTypeName(handlerType);
handleTwoMessageAsync(multiMessageDispatching, handlerProxy, handlerTypeName, queueHandler, 0);
}
private void dispatchThreeMessageToHandlerAsync(MultiMessageDisptaching multiMessageDispatching, IMessageHandlerProxy3 handlerProxy, QueuedHandler queueHandler, int retryTimes) {
Class> handlerType = handlerProxy.getInnerObject().getClass();
String handlerTypeName = typeNameProvider.getTypeName(handlerType);
handleThreeMessageAsync(multiMessageDispatching, handlerProxy, handlerTypeName, queueHandler, 0);
}
private void handleSingleMessageAsync(SingleMessageDispatching singleMessageDispatching, IMessageHandlerProxy1 handlerProxy, String handlerTypeName, String messageTypeName, QueuedHandler queueHandler, int retryTimes) {
IMessage message = singleMessageDispatching.getMessage();
IOHelper.tryAsyncActionRecursivelyWithoutResult("HandleSingleMessageAsync",
() -> handlerProxy.handleAsync(message),
result -> {
singleMessageDispatching.removeHandledHandler(handlerTypeName);
if (queueHandler != null) {
queueHandler.onHandlerFinished(handlerProxy);
}
if (logger.isDebugEnabled()) {
logger.debug("Message handled success, handlerType:{}, messageType:{}, messageId:{}", handlerTypeName, message.getClass().getName(), message.getId());
}
},
() -> String.format("[messageId:%s, messageType:%s, handlerType:%s]", message.getId(), message.getClass().getName(), handlerProxy.getInnerObject().getClass().getName()),
null, retryTimes, true);
}
private void handleTwoMessageAsync(MultiMessageDisptaching multiMessageDispatching, IMessageHandlerProxy2 handlerProxy, String handlerTypeName, QueuedHandler queueHandler, int retryTimes) {
IMessage[] messages = multiMessageDispatching.getMessages();
IMessage message1 = messages[0];
IMessage message2 = messages[1];
IOHelper.tryAsyncActionRecursively("HandleTwoMessageAsync",
() -> handlerProxy.handleAsync(message1, message2),
result ->
{
multiMessageDispatching.removeHandledHandler(handlerTypeName);
if (queueHandler != null) {
queueHandler.onHandlerFinished(handlerProxy);
}
if (logger.isDebugEnabled()) {
logger.debug("TwoMessage handled success, [messages:{}], handlerType:{}]", String.join("|", Arrays.stream(messages).map(x -> String.format("id:%s,type:%s", x.getId(), x.getClass().getName())).collect(Collectors.toList())), handlerTypeName);
}
},
() -> String.format("[messages:%s, handlerType:%s]", String.join("|", Arrays.stream(messages).map(x -> String.format("id:%s,type:%s", x.getId(), x.getClass().getName())).collect(Collectors.toList())), handlerProxy.getInnerObject().getClass().getName()),
null, retryTimes, true);
}
private void handleThreeMessageAsync(
MultiMessageDisptaching multiMessageDispatching, IMessageHandlerProxy3 handlerProxy, String handlerTypeName,
QueuedHandler queueHandler, int retryTimes) {
IMessage[] messages = multiMessageDispatching.getMessages();
IMessage message1 = messages[0];
IMessage message2 = messages[1];
IMessage message3 = messages[2];
IOHelper.tryAsyncActionRecursively("HandleThreeMessageAsync",
() -> handlerProxy.handleAsync(message1, message2, message3),
result ->
{
multiMessageDispatching.removeHandledHandler(handlerTypeName);
if (queueHandler != null) {
queueHandler.onHandlerFinished(handlerProxy);
}
if (logger.isDebugEnabled()) {
logger.debug("ThreeMessage handled success, [messages:{}, handlerType:{}]", Arrays.stream(messages).map(x -> String.format("id:%s,type:%s", x.getId(), x.getClass().getName())).collect(Collectors.joining("|")), handlerTypeName);
}
},
() -> String.format("[messages:%s, handlerType:%s]", Arrays.stream(messages).map(x -> String.format("id:%s,type:%s", x.getId(), x.getClass().getName())).collect(Collectors.joining("|")), handlerProxy.getInnerObject().getClass().getName()),
null, retryTimes, true);
}
static class QueuedHandler {
private final Action2, T> dispatchToNextHandler;
private final ConcurrentLinkedQueue handlerQueue;
public QueuedHandler(List handlers, Action2, T> dispatchToNextHandler) {
handlerQueue = new ConcurrentLinkedQueue<>();
handlerQueue.addAll(handlers);
this.dispatchToNextHandler = dispatchToNextHandler;
}
public T dequeueHandler() {
return handlerQueue.poll();
}
public void onHandlerFinished(T handler) {
T nextHandler = dequeueHandler();
if (nextHandler != null) {
dispatchToNextHandler.apply(this, nextHandler);
}
}
}
class RootDispatching {
private final CompletableFuture taskCompletionSource;
private final ConcurrentMap