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

org.enodeframework.queue.DefaultSendReplyService.kt Maven / Gradle / Ivy

There is a newer version: 1.1.10
Show newest version
package org.enodeframework.queue

import com.google.common.cache.CacheBuilder
import io.vertx.core.AsyncResult
import io.vertx.core.Promise
import io.vertx.core.json.JsonObject
import io.vertx.core.net.NetClient
import io.vertx.core.net.NetSocket
import io.vertx.core.net.SocketAddress
import io.vertx.ext.eventbus.bridge.tcp.impl.protocol.FrameHelper
import io.vertx.ext.eventbus.bridge.tcp.impl.protocol.FrameParser
import io.vertx.kotlin.coroutines.CoroutineVerticle
import org.enodeframework.commanding.CommandResult
import org.enodeframework.commanding.CommandReturnType
import org.enodeframework.common.io.ReplySocketAddress
import org.enodeframework.common.io.Task
import org.enodeframework.common.serializing.ISerializeService
import org.enodeframework.common.utilities.InetUtil
import org.enodeframework.common.utilities.ReplyMessage
import org.enodeframework.queue.domainevent.DomainEventHandledMessage
import org.slf4j.LoggerFactory
import java.time.Duration
import java.util.concurrent.CompletableFuture

/**
 * @author [email protected]
 * TODO 支持其他类型的服务间调用
 */
class DefaultSendReplyService(private val serializeService: ISerializeService) : CoroutineVerticle(), ISendReplyService {
    private var started = false
    private var stoped = false
    private lateinit var netClient: NetClient
    private val netSocketCache = CacheBuilder.newBuilder()
            .expireAfterWrite(Duration.ofMinutes(10))
            .maximumSize(10)
            .build?>()

    override suspend fun start() {
        if (!started) {
            netClient = vertx.createNetClient()
            started = true
        }
    }

    override suspend fun stop() {
        if (!stoped) {
            netClient.close()
            stoped = true
        }
    }

    override fun sendCommandReply(commandResult: CommandResult, replyAddress: ReplySocketAddress): CompletableFuture {
        val replyMessage = ReplyMessage()
        replyMessage.code = CommandReturnType.CommandExecuted.value
        replyMessage.commandResult = commandResult
        return sendReply(replyMessage, replyAddress)
    }

    override fun sendEventReply(eventHandledMessage: DomainEventHandledMessage, replyAddress: ReplySocketAddress): CompletableFuture {
        val replyMessage = ReplyMessage()
        replyMessage.code = CommandReturnType.EventHandled.value
        replyMessage.eventHandledMessage = eventHandledMessage
        return sendReply(replyMessage, replyAddress)
    }

    fun sendReply(replyMessage: ReplyMessage?, replySocketAddress: ReplySocketAddress): CompletableFuture {
        val socketAddress = SocketAddress.inetSocketAddress(replySocketAddress.port, replySocketAddress.host)
        val message = serializeService.serialize(replyMessage)
        val address = InetUtil.toUri(replySocketAddress)
        val replyAddress = String.format("%s.%s", "client", address)
        var promise = netSocketCache.getIfPresent(address)
        if (promise == null) {
            promise = Promise.promise()
            netSocketCache.put(address, promise)
            netClient.connect(socketAddress, promise)
        }
        promise!!.future().onFailure { throwable: Throwable? ->
            netSocketCache.invalidate(address)
            logger.error("connect occurs unexpected error, msg: {}", message, throwable)
        }.onSuccess { socket: NetSocket ->
            socket.exceptionHandler { throwable: Throwable? ->
                netSocketCache.invalidate(address)
                socket.close()
                logger.error("socket occurs unexpected error, msg: {}", message, throwable)
            }
            socket.closeHandler {
                netSocketCache.invalidate(address)
                logger.error("socket closed, indicatedServerName: {},writeHandlerID: {}", socket.indicatedServerName(), socket.writeHandlerID())
            }
            socket.handler(FrameParser { parse: AsyncResult ->
                if (parse.succeeded()) {
                    logger.info("receive server req: {}, res: {}", message, parse)
                }
            })
            socket.endHandler { netSocketCache.invalidate(address) }
            FrameHelper.sendFrame("send", address, replyAddress, JsonObject(message), socket)
        }
        return Task.completedTask
    }

    companion object {
        private val logger = LoggerFactory.getLogger(DefaultSendReplyService::class.java)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy