
org.enodeframework.mysql.handler.MySQLAddDomainEventsHandler.kt Maven / Gradle / Ivy
package org.enodeframework.mysql.handler
import com.google.common.base.Strings
import com.google.common.collect.Lists
import io.vertx.core.AsyncResult
import io.vertx.core.Handler
import io.vertx.mysqlclient.MySQLException
import io.vertx.sqlclient.Row
import io.vertx.sqlclient.RowSet
import org.enodeframework.common.exception.EventStoreException
import org.enodeframework.common.exception.IORuntimeException
import org.enodeframework.configurations.EventStoreConfiguration
import org.enodeframework.eventing.AggregateEventAppendResult
import org.enodeframework.eventing.EventAppendStatus
import org.slf4j.LoggerFactory
import java.util.concurrent.CompletableFuture
import java.util.regex.Pattern
class MySQLAddDomainEventsHandler(private val configuration: EventStoreConfiguration) :
Handler>> {
private val code: String = "23000"
companion object {
private val logger = LoggerFactory.getLogger(MySQLAddDomainEventsHandler::class.java)
private val PATTERN_MYSQL = Pattern.compile("^Duplicate entry '.*-(.*)' for key")
}
var future = CompletableFuture()
private fun getDuplicatedId(message: String): String {
val matcher = PATTERN_MYSQL.matcher(message)
if (!matcher.find()) {
return ""
}
return if (matcher.groupCount() == 0) {
""
} else matcher.group(1)
}
override fun handle(ar: AsyncResult>) {
if (ar.succeeded()) {
val appendResult = AggregateEventAppendResult()
appendResult.eventAppendStatus = EventAppendStatus.Success
future.complete(appendResult)
return
}
val throwable = ar.cause()
if (throwable is MySQLException) {
if (code == throwable.sqlState && throwable.message?.contains(configuration.eventVersionUkName) == true) {
val appendResult = AggregateEventAppendResult()
appendResult.eventAppendStatus = EventAppendStatus.DuplicateEvent
future.complete(appendResult)
return
}
if (code == throwable.sqlState && throwable.message?.contains(configuration.eventCommandIdUkName) == true) {
// 不同的数据库在冲突时的错误信息不同,可以通过解析错误信息的方式将冲突的commandId找出来,这里要求id不能命中正则的规则(不包含-字符)
val appendResult = AggregateEventAppendResult()
appendResult.eventAppendStatus = EventAppendStatus.DuplicateCommand
val commandId = this.getDuplicatedId(throwable.message ?: "")
if (!Strings.isNullOrEmpty(commandId)) {
appendResult.duplicateCommandIds = Lists.newArrayList(commandId)
}
// 如果没有从异常信息获取到commandId(很低概率获取不到),需要从db查询出来
// 但是Vert.x的线程模型决定了不能再次使用EventLoop线程执行阻塞的查询操作
future.complete(appendResult)
return
}
logger.error("Batch append event has sql exception.", throwable)
future.completeExceptionally(IORuntimeException(throwable))
return
}
logger.error("Batch append event has unknown exception.", throwable)
future.completeExceptionally(EventStoreException(throwable))
return
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy