All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.enodeframework.queue.command.DefaultCommandBus.kt Maven / Gradle / Ivy

package org.enodeframework.queue.command

import kotlinx.coroutines.future.await
import org.enodeframework.commanding.CommandBus
import org.enodeframework.commanding.CommandMessage
import org.enodeframework.commanding.CommandResult
import org.enodeframework.commanding.CommandReturnType
import org.enodeframework.common.serializing.SerializeService
import org.enodeframework.common.utils.Assert
import org.enodeframework.queue.MessageTypeCode
import org.enodeframework.queue.QueueMessage
import org.enodeframework.queue.SendMessageResult
import org.enodeframework.queue.SendMessageService
import java.util.concurrent.CompletableFuture

/**
 * @author [email protected]
 */
class DefaultCommandBus(
    private val topic: String,
    private val tag: String,
    private val commandResultProcessor: CommandResultProcessor,
    private val sendMessageService: SendMessageService,
    private val serializeService: SerializeService,
) : CommandBus {
    override fun sendAsync(command: CommandMessage): CompletableFuture {
        return sendMessageService.sendMessageAsync(buildCommandMessage(command, false))
    }

    override suspend fun send(command: CommandMessage): SendMessageResult {
        return sendAsync(command).await()
    }

    override fun executeAsync(command: CommandMessage): CompletableFuture {
        return executeAsync(command, CommandReturnType.CommandExecuted)
    }

    override fun executeAsync(
        command: CommandMessage,
        commandReturnType: CommandReturnType
    ): CompletableFuture {
        val taskCompletionSource = CompletableFuture()
        try {
            Assert.nonNull(commandResultProcessor, "commandResultProcessor")
            commandResultProcessor.registerProcessingCommand(command, commandReturnType, taskCompletionSource)
            val sendMessageAsync = sendMessageService.sendMessageAsync(buildCommandMessage(command, true))
            sendMessageAsync.exceptionally { ex: Throwable ->
                commandResultProcessor.processFailedSendingCommand(command)
                taskCompletionSource.completeExceptionally(ex)
                null
            }
        } catch (ex: Exception) {
            taskCompletionSource.completeExceptionally(ex)
        }
        return taskCompletionSource
    }

    override suspend fun execute(command: CommandMessage): CommandResult {
        return executeAsync(command).await()
    }

    override suspend fun execute(command: CommandMessage, commandReturnType: CommandReturnType): CommandResult {
        return executeAsync(command, commandReturnType).await()
    }

    private fun buildCommandMessage(command: CommandMessage, needReply: Boolean): QueueMessage {
        Assert.nonNull(command.aggregateRootId, "aggregateRootId")
        Assert.nonNull(topic, "topic")
        val commandData = serializeService.serialize(command)
        val genericCommandMessage = GenericCommandMessage()
        if (needReply) {
            genericCommandMessage.replyAddress = commandResultProcessor.getBindAddress()
        }
        genericCommandMessage.commandData = commandData
        genericCommandMessage.commandType = command.javaClass.name
        val messageData = serializeService.serialize(genericCommandMessage)
        val queueMessage = QueueMessage()
        queueMessage.topic = topic
        queueMessage.tag = tag
        queueMessage.body = messageData
        queueMessage.type = MessageTypeCode.CommandMessage.value
        queueMessage.routeKey = command.aggregateRootId
        val key = "${command.id}_cmd_agg_${command.aggregateRootId}"
        queueMessage.key = key
        return queueMessage
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy