fix: 修复 CopyOrderTrackingService 和 CopyTradingService 的 @Transactional 自调用问题

1. CopyOrderTrackingService 修复
   - 实现 ApplicationContextAware 接口
   - 添加 getSelf() 方法获取代理对象
   - 在 processTrade() 中通过代理调用 processBuyTrade() 和 processSellTrade()
   - 确保两个子方法的 @Transactional 生效

2. CopyTradingService 修复
   - 实现 ApplicationContextAware 接口
   - 添加 getSelf() 方法获取代理对象
   - 在 updateCopyTradingStatus() 中通过代理调用 updateCopyTrading()
   - 确保内部调用的 @Transactional 生效

修改的文件:
- CopyOrderTrackingService.kt
- CopyTradingService.kt
This commit is contained in:
WrBug
2026-01-16 10:28:39 +08:00
parent ae68a33c1e
commit 3e2e97e572
2 changed files with 40 additions and 7 deletions
@@ -14,6 +14,8 @@ import com.wrbug.polymarketbot.util.IllegalBigDecimal
import com.wrbug.polymarketbot.util.JsonUtils
import com.wrbug.polymarketbot.util.toSafeBigDecimal
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.math.BigDecimal
@@ -30,10 +32,24 @@ class CopyTradingService(
private val monitorService: CopyTradingMonitorService,
private val jsonUtils: JsonUtils,
private val gson: Gson
) {
) : ApplicationContextAware {
private val logger = LoggerFactory.getLogger(CopyTradingService::class.java)
private var applicationContext: ApplicationContext? = null
override fun setApplicationContext(applicationContext: ApplicationContext) {
this.applicationContext = applicationContext
}
/**
* 获取代理对象,用于解决 @Transactional 自调用问题
*/
private fun getSelf(): CopyTradingService {
return applicationContext?.getBean(CopyTradingService::class.java)
?: throw IllegalStateException("ApplicationContext not initialized")
}
/**
* 创建跟单配置
* 支持两种方式:
@@ -331,7 +347,7 @@ class CopyTradingService(
*/
@Transactional
fun updateCopyTradingStatus(request: CopyTradingUpdateStatusRequest): Result<CopyTradingDto> {
return updateCopyTrading(
return getSelf().updateCopyTrading(
CopyTradingUpdateRequest(
copyTradingId = request.copyTradingId,
enabled = request.enabled
@@ -23,6 +23,8 @@ import com.wrbug.polymarketbot.service.common.MarketService
import com.wrbug.polymarketbot.service.common.PolymarketClobService
import com.wrbug.polymarketbot.service.system.TelegramNotificationService
import com.wrbug.polymarketbot.util.CryptoUtils
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.math.BigDecimal
@@ -51,12 +53,26 @@ open class CopyOrderTrackingService(
private val cryptoUtils: CryptoUtils,
private val marketService: MarketService, // 市场信息服务
private val telegramNotificationService: TelegramNotificationService? = null // 可选,避免循环依赖
) {
) : ApplicationContextAware {
private val logger = LoggerFactory.getLogger(CopyOrderTrackingService::class.java)
// 协程作用域(用于异步发送通知)
private val notificationScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private var applicationContext: ApplicationContext? = null
override fun setApplicationContext(applicationContext: ApplicationContext) {
this.applicationContext = applicationContext
}
/**
* 获取代理对象,用于解决 @Transactional 自调用问题
*/
private fun getSelf(): CopyOrderTrackingService {
return applicationContext?.getBean(CopyOrderTrackingService::class.java)
?: throw IllegalStateException("ApplicationContext not initialized")
}
// 使用 Mutex 保证线程安全(按交易ID锁定)
private val tradeMutexMap = ConcurrentHashMap<String, Mutex>()
@@ -138,10 +154,11 @@ open class CopyOrderTrackingService(
return@withLock Result.success(Unit)
}
// 2. 处理交易逻辑
// 2. 处理交易逻辑(通过代理对象调用,确保 @Transactional 生效)
val self = getSelf()
val result = when (trade.side.uppercase()) {
"BUY" -> processBuyTrade(leaderId, trade, source)
"SELL" -> processSellTrade(leaderId, trade)
"BUY" -> self.processBuyTrade(leaderId, trade, source)
"SELL" -> self.processSellTrade(leaderId, trade)
else -> {
logger.warn("未知的交易方向: ${trade.side}")
Result.failure(IllegalArgumentException("未知的交易方向: ${trade.side}"))