refactor: 统一使用 MarketService 并改用 LRU 缓存
主要改进: 1. 将 MarketService 缓存从 ConcurrentHashMap 改为 Caffeine LRU 缓存 - 最多缓存 200 条市场记录 - 自动淘汰最近最少使用的记录 - 提高缓存命中率和性能 2. 添加 Caffeine 依赖 (com.github.ben-manes.caffeine:caffeine:3.1.8) 3. 重构以下服务,统一使用 MarketService 获取市场信息: - OrderPushService: 删除 fetchMarketInfo() 方法,直接使用 MarketService - CopyOrderTrackingService: 移除直接调用 Gamma API 的代码 - AccountService: 订单通知中使用 MarketService - OrderStatusUpdateService: 买入/卖出订单通知使用 MarketService 优势: - 减少重复的 API 调用,利用三级缓存(内存 → 数据库 → API) - 提高代码一致性和可维护性 - 统一市场数据获取逻辑,便于后续扩展
This commit is contained in:
@@ -68,6 +68,9 @@ dependencies {
|
|||||||
// Logging
|
// Logging
|
||||||
implementation("org.slf4j:slf4j-api")
|
implementation("org.slf4j:slf4j-api")
|
||||||
|
|
||||||
|
// Caffeine Cache (LRU)
|
||||||
|
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test")
|
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test")
|
||||||
|
|||||||
+14
-51
@@ -11,6 +11,7 @@ import com.wrbug.polymarketbot.util.JsonUtils
|
|||||||
import com.wrbug.polymarketbot.util.getEventSlug
|
import com.wrbug.polymarketbot.util.getEventSlug
|
||||||
import com.wrbug.polymarketbot.service.common.PolymarketClobService
|
import com.wrbug.polymarketbot.service.common.PolymarketClobService
|
||||||
import com.wrbug.polymarketbot.service.common.BlockchainService
|
import com.wrbug.polymarketbot.service.common.BlockchainService
|
||||||
|
import com.wrbug.polymarketbot.service.common.MarketService
|
||||||
import com.wrbug.polymarketbot.service.common.PolymarketApiKeyService
|
import com.wrbug.polymarketbot.service.common.PolymarketApiKeyService
|
||||||
import com.wrbug.polymarketbot.service.copytrading.orders.OrderPushService
|
import com.wrbug.polymarketbot.service.copytrading.orders.OrderPushService
|
||||||
import com.wrbug.polymarketbot.service.copytrading.orders.OrderSigningService
|
import com.wrbug.polymarketbot.service.copytrading.orders.OrderSigningService
|
||||||
@@ -37,6 +38,7 @@ class AccountService(
|
|||||||
private val orderPushService: OrderPushService,
|
private val orderPushService: OrderPushService,
|
||||||
private val orderSigningService: OrderSigningService,
|
private val orderSigningService: OrderSigningService,
|
||||||
private val cryptoUtils: CryptoUtils,
|
private val cryptoUtils: CryptoUtils,
|
||||||
|
private val marketService: MarketService, // 市场信息服务
|
||||||
private val telegramNotificationService: TelegramNotificationService? = null, // 可选,避免循环依赖
|
private val telegramNotificationService: TelegramNotificationService? = null, // 可选,避免循环依赖
|
||||||
private val relayClientService: RelayClientService,
|
private val relayClientService: RelayClientService,
|
||||||
private val jsonUtils: JsonUtils
|
private val jsonUtils: JsonUtils
|
||||||
@@ -935,22 +937,9 @@ class AccountService(
|
|||||||
notificationScope.launch {
|
notificationScope.launch {
|
||||||
try {
|
try {
|
||||||
// 获取市场信息(标题和slug)
|
// 获取市场信息(标题和slug)
|
||||||
val marketInfo = withContext(Dispatchers.IO) {
|
val market = marketService.getMarket(request.marketId)
|
||||||
try {
|
val marketTitle = market?.title ?: request.marketId
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
val marketSlug = market?.eventSlug // 跳转用的 slug
|
||||||
val marketResponse = gammaApi.listMarkets(conditionIds = listOf(request.marketId))
|
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketResponse.body()!!.firstOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.warn("获取市场信息失败: ${e.message}", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val marketTitle = marketInfo?.question ?: request.marketId
|
|
||||||
|
|
||||||
// 获取当前语言设置(从 LocaleContextHolder)
|
// 获取当前语言设置(从 LocaleContextHolder)
|
||||||
val locale = try {
|
val locale = try {
|
||||||
@@ -963,7 +952,7 @@ class AccountService(
|
|||||||
orderId = orderId,
|
orderId = orderId,
|
||||||
marketTitle = marketTitle,
|
marketTitle = marketTitle,
|
||||||
marketId = request.marketId,
|
marketId = request.marketId,
|
||||||
marketSlug = marketInfo.getEventSlug(), // 跳转用的 slug
|
marketSlug = marketSlug,
|
||||||
side = request.side,
|
side = request.side,
|
||||||
price = sellPrice, // 直接传递卖出价格
|
price = sellPrice, // 直接传递卖出价格
|
||||||
size = sellQuantity.toPlainString(), // 直接传递卖出数量
|
size = sellQuantity.toPlainString(), // 直接传递卖出数量
|
||||||
@@ -1002,22 +991,9 @@ class AccountService(
|
|||||||
notificationScope.launch {
|
notificationScope.launch {
|
||||||
try {
|
try {
|
||||||
// 获取市场信息(标题和slug)
|
// 获取市场信息(标题和slug)
|
||||||
val marketInfo = withContext(Dispatchers.IO) {
|
val market = marketService.getMarket(request.marketId)
|
||||||
try {
|
val marketTitle = market?.title ?: request.marketId
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
val marketSlug = market?.eventSlug // 跳转用的 slug
|
||||||
val marketResponse = gammaApi.listMarkets(conditionIds = listOf(request.marketId))
|
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketResponse.body()!!.firstOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.warn("获取市场信息失败: ${e.message}", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val marketTitle = marketInfo?.question ?: request.marketId
|
|
||||||
|
|
||||||
// 获取当前语言设置(从 LocaleContextHolder)
|
// 获取当前语言设置(从 LocaleContextHolder)
|
||||||
val locale = try {
|
val locale = try {
|
||||||
@@ -1029,7 +1005,7 @@ class AccountService(
|
|||||||
telegramNotificationService?.sendOrderFailureNotification(
|
telegramNotificationService?.sendOrderFailureNotification(
|
||||||
marketTitle = marketTitle,
|
marketTitle = marketTitle,
|
||||||
marketId = request.marketId,
|
marketId = request.marketId,
|
||||||
marketSlug = marketInfo.getEventSlug(), // 跳转用的 slug
|
marketSlug = marketSlug,
|
||||||
side = request.side,
|
side = request.side,
|
||||||
outcome = null, // 失败时可能没有 outcome
|
outcome = null, // 失败时可能没有 outcome
|
||||||
price = if (request.orderType == "LIMIT") sellPrice.toString() else "MARKET",
|
price = if (request.orderType == "LIMIT") sellPrice.toString() else "MARKET",
|
||||||
@@ -1059,22 +1035,9 @@ class AccountService(
|
|||||||
notificationScope.launch {
|
notificationScope.launch {
|
||||||
try {
|
try {
|
||||||
// 获取市场信息(标题和slug)
|
// 获取市场信息(标题和slug)
|
||||||
val marketInfo = withContext(Dispatchers.IO) {
|
val market = marketService.getMarket(request.marketId)
|
||||||
try {
|
val marketTitle = market?.title ?: request.marketId
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
val marketSlug = market?.eventSlug // 跳转用的 slug
|
||||||
val marketResponse = gammaApi.listMarkets(conditionIds = listOf(request.marketId))
|
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketResponse.body()!!.firstOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.warn("获取市场信息失败: ${e.message}", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val marketTitle = marketInfo?.question ?: request.marketId
|
|
||||||
|
|
||||||
// 获取当前语言设置(从 LocaleContextHolder)
|
// 获取当前语言设置(从 LocaleContextHolder)
|
||||||
val locale = try {
|
val locale = try {
|
||||||
@@ -1089,7 +1052,7 @@ class AccountService(
|
|||||||
telegramNotificationService?.sendOrderFailureNotification(
|
telegramNotificationService?.sendOrderFailureNotification(
|
||||||
marketTitle = marketTitle,
|
marketTitle = marketTitle,
|
||||||
marketId = request.marketId,
|
marketId = request.marketId,
|
||||||
marketSlug = marketInfo.getEventSlug(), // 跳转用的 slug
|
marketSlug = marketSlug,
|
||||||
side = request.side,
|
side = request.side,
|
||||||
outcome = null, // 失败时可能没有 outcome
|
outcome = null, // 失败时可能没有 outcome
|
||||||
price = if (request.orderType == "LIMIT") sellPrice.toString() else "MARKET",
|
price = if (request.orderType == "LIMIT") sellPrice.toString() else "MARKET",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.wrbug.polymarketbot.service.common
|
package com.wrbug.polymarketbot.service.common
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine
|
||||||
import com.wrbug.polymarketbot.api.MarketResponse
|
import com.wrbug.polymarketbot.api.MarketResponse
|
||||||
import com.wrbug.polymarketbot.api.PolymarketGammaApi
|
import com.wrbug.polymarketbot.api.PolymarketGammaApi
|
||||||
import com.wrbug.polymarketbot.entity.Market
|
import com.wrbug.polymarketbot.entity.Market
|
||||||
@@ -9,7 +11,6 @@ import com.wrbug.polymarketbot.util.getEventSlug
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 市场信息服务
|
* 市场信息服务
|
||||||
@@ -23,8 +24,10 @@ class MarketService(
|
|||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(MarketService::class.java)
|
private val logger = LoggerFactory.getLogger(MarketService::class.java)
|
||||||
|
|
||||||
// 内存缓存(避免频繁查询数据库)
|
// LRU 缓存(避免频繁查询数据库),最多缓存 200 条记录
|
||||||
private val marketCache = ConcurrentHashMap<String, Market>()
|
private val marketCache: Cache<String, Market> = Caffeine.newBuilder()
|
||||||
|
.maximumSize(200) // 最多缓存 200 条记录
|
||||||
|
.build()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据市场ID获取市场信息
|
* 根据市场ID获取市场信息
|
||||||
@@ -32,12 +35,12 @@ class MarketService(
|
|||||||
*/
|
*/
|
||||||
fun getMarket(marketId: String): Market? {
|
fun getMarket(marketId: String): Market? {
|
||||||
// 1. 从缓存获取
|
// 1. 从缓存获取
|
||||||
marketCache[marketId]?.let { return it }
|
marketCache.getIfPresent(marketId)?.let { return it }
|
||||||
|
|
||||||
// 2. 从数据库查询
|
// 2. 从数据库查询
|
||||||
val market = marketRepository.findByMarketId(marketId)
|
val market = marketRepository.findByMarketId(marketId)
|
||||||
if (market != null) {
|
if (market != null) {
|
||||||
marketCache[marketId] = market
|
marketCache.put(marketId, market)
|
||||||
return market
|
return market
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +55,7 @@ class MarketService(
|
|||||||
|
|
||||||
// 再次从数据库查询(API可能已经保存)
|
// 再次从数据库查询(API可能已经保存)
|
||||||
return marketRepository.findByMarketId(marketId)?.also {
|
return marketRepository.findByMarketId(marketId)?.also {
|
||||||
marketCache[marketId] = it
|
marketCache.put(marketId, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +90,7 @@ class MarketService(
|
|||||||
val savedMarkets = marketRepository.findByMarketIdIn(missingIds)
|
val savedMarkets = marketRepository.findByMarketIdIn(missingIds)
|
||||||
for (market in savedMarkets) {
|
for (market in savedMarkets) {
|
||||||
result[market.marketId] = market
|
result[market.marketId] = market
|
||||||
marketCache[market.marketId] = market
|
marketCache.put(market.marketId, market)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +195,7 @@ class MarketService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val savedMarket = marketRepository.save(market)
|
val savedMarket = marketRepository.save(market)
|
||||||
marketCache[marketId] = savedMarket
|
marketCache.put(marketId, savedMarket)
|
||||||
savedMarket
|
savedMarket
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error("保存市场信息失败: marketId=$marketId, error=${e.message}", e)
|
logger.error("保存市场信息失败: marketId=$marketId, error=${e.message}", e)
|
||||||
@@ -204,7 +207,7 @@ class MarketService(
|
|||||||
* 清除缓存(用于测试或手动刷新)
|
* 清除缓存(用于测试或手动刷新)
|
||||||
*/
|
*/
|
||||||
fun clearCache() {
|
fun clearCache() {
|
||||||
marketCache.clear()
|
marketCache.invalidateAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-42
@@ -1,9 +1,7 @@
|
|||||||
package com.wrbug.polymarketbot.service.copytrading.orders
|
package com.wrbug.polymarketbot.service.copytrading.orders
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.wrbug.polymarketbot.api.MarketResponse
|
|
||||||
import com.wrbug.polymarketbot.dto.OrderDetailDto
|
import com.wrbug.polymarketbot.dto.OrderDetailDto
|
||||||
import com.wrbug.polymarketbot.util.getEventSlug
|
|
||||||
import com.wrbug.polymarketbot.dto.OrderMessageDto
|
import com.wrbug.polymarketbot.dto.OrderMessageDto
|
||||||
import com.wrbug.polymarketbot.dto.OrderPushMessage
|
import com.wrbug.polymarketbot.dto.OrderPushMessage
|
||||||
import com.wrbug.polymarketbot.entity.Account
|
import com.wrbug.polymarketbot.entity.Account
|
||||||
@@ -20,6 +18,7 @@ import com.wrbug.polymarketbot.util.CryptoUtils
|
|||||||
import com.wrbug.polymarketbot.repository.CopyOrderTrackingRepository
|
import com.wrbug.polymarketbot.repository.CopyOrderTrackingRepository
|
||||||
import com.wrbug.polymarketbot.repository.CopyTradingRepository
|
import com.wrbug.polymarketbot.repository.CopyTradingRepository
|
||||||
import com.wrbug.polymarketbot.repository.LeaderRepository
|
import com.wrbug.polymarketbot.repository.LeaderRepository
|
||||||
|
import com.wrbug.polymarketbot.service.common.MarketService
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
@@ -36,7 +35,8 @@ class OrderPushService(
|
|||||||
private val cryptoUtils: CryptoUtils,
|
private val cryptoUtils: CryptoUtils,
|
||||||
private val copyOrderTrackingRepository: CopyOrderTrackingRepository? = null, // 可选,避免循环依赖
|
private val copyOrderTrackingRepository: CopyOrderTrackingRepository? = null, // 可选,避免循环依赖
|
||||||
private val copyTradingRepository: CopyTradingRepository? = null, // 可选,避免循环依赖
|
private val copyTradingRepository: CopyTradingRepository? = null, // 可选,避免循环依赖
|
||||||
private val leaderRepository: LeaderRepository? = null // 可选,避免循环依赖
|
private val leaderRepository: LeaderRepository? = null, // 可选,避免循环依赖
|
||||||
|
private val marketService: MarketService // 市场信息服务
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(OrderPushService::class.java)
|
private val logger = LoggerFactory.getLogger(OrderPushService::class.java)
|
||||||
@@ -423,8 +423,8 @@ class OrderPushService(
|
|||||||
|
|
||||||
result.fold(
|
result.fold(
|
||||||
onSuccess = { openOrder ->
|
onSuccess = { openOrder ->
|
||||||
// 获取市场信息(通过 Gamma API)
|
// 获取市场信息(使用 MarketService,优先从数据库/缓存获取)
|
||||||
val marketInfo = fetchMarketInfo(conditionId ?: openOrder.market)
|
val market = marketService.getMarket(conditionId ?: openOrder.market)
|
||||||
|
|
||||||
// 转换为 DTO
|
// 转换为 DTO
|
||||||
// 注意:createdAt 是 unix timestamp (Long),需要转换为字符串
|
// 注意:createdAt 是 unix timestamp (Long),需要转换为字符串
|
||||||
@@ -437,9 +437,9 @@ class OrderPushService(
|
|||||||
filled = openOrder.sizeMatched, // 使用 size_matched
|
filled = openOrder.sizeMatched, // 使用 size_matched
|
||||||
status = openOrder.status,
|
status = openOrder.status,
|
||||||
createdAt = openOrder.createdAt.toString(), // unix timestamp 转换为字符串
|
createdAt = openOrder.createdAt.toString(), // unix timestamp 转换为字符串
|
||||||
marketName = marketInfo?.question,
|
marketName = market?.title,
|
||||||
marketSlug = marketInfo?.slug, // 显示用的 slug
|
marketSlug = market?.slug, // 显示用的 slug
|
||||||
marketIcon = marketInfo?.icon
|
marketIcon = market?.icon
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onFailure = { e ->
|
onFailure = { e ->
|
||||||
@@ -453,40 +453,6 @@ class OrderPushService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取市场信息(通过 Gamma API)
|
|
||||||
* 文档: https://docs.polymarket.com/api-reference/markets/list-markets
|
|
||||||
*
|
|
||||||
* 使用 /markets 接口,通过 condition_ids 查询参数获取市场信息
|
|
||||||
* 订单返回的 market 字段是 16 进制的 condition ID(如 "0x...")
|
|
||||||
*/
|
|
||||||
private suspend fun fetchMarketInfo(conditionId: String): MarketResponse? {
|
|
||||||
return try {
|
|
||||||
// 创建 Gamma API 客户端(公开 API,不需要认证)
|
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
|
||||||
|
|
||||||
// 调用 Gamma API 获取市场信息
|
|
||||||
// 使用 /markets 接口,通过 condition_ids 查询参数
|
|
||||||
val response = gammaApi.listMarkets(
|
|
||||||
conditionIds = listOf(conditionId),
|
|
||||||
includeTag = null
|
|
||||||
)
|
|
||||||
if (response.isSuccessful && response.body() != null) {
|
|
||||||
val markets = response.body()!!
|
|
||||||
if (markets.isNotEmpty()) {
|
|
||||||
val market = markets.first()
|
|
||||||
return market
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订阅账户的订单推送(保留用于向后兼容)
|
* 订阅账户的订单推送(保留用于向后兼容)
|
||||||
*/
|
*/
|
||||||
|
|||||||
+12
-42
@@ -7,7 +7,6 @@ import com.wrbug.polymarketbot.entity.*
|
|||||||
import com.wrbug.polymarketbot.repository.*
|
import com.wrbug.polymarketbot.repository.*
|
||||||
import com.wrbug.polymarketbot.util.RetrofitFactory
|
import com.wrbug.polymarketbot.util.RetrofitFactory
|
||||||
import com.wrbug.polymarketbot.util.*
|
import com.wrbug.polymarketbot.util.*
|
||||||
import com.wrbug.polymarketbot.util.getEventSlug
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
@@ -20,6 +19,7 @@ import com.wrbug.polymarketbot.service.copytrading.configs.CopyTradingFilterServ
|
|||||||
import com.wrbug.polymarketbot.service.copytrading.configs.FilterStatus
|
import com.wrbug.polymarketbot.service.copytrading.configs.FilterStatus
|
||||||
import com.wrbug.polymarketbot.service.copytrading.orders.OrderSigningService
|
import com.wrbug.polymarketbot.service.copytrading.orders.OrderSigningService
|
||||||
import com.wrbug.polymarketbot.service.common.BlockchainService
|
import com.wrbug.polymarketbot.service.common.BlockchainService
|
||||||
|
import com.wrbug.polymarketbot.service.common.MarketService
|
||||||
import com.wrbug.polymarketbot.service.common.PolymarketClobService
|
import com.wrbug.polymarketbot.service.common.PolymarketClobService
|
||||||
import com.wrbug.polymarketbot.service.system.TelegramNotificationService
|
import com.wrbug.polymarketbot.service.system.TelegramNotificationService
|
||||||
import com.wrbug.polymarketbot.util.CryptoUtils
|
import com.wrbug.polymarketbot.util.CryptoUtils
|
||||||
@@ -49,6 +49,7 @@ open class CopyOrderTrackingService(
|
|||||||
private val clobService: PolymarketClobService,
|
private val clobService: PolymarketClobService,
|
||||||
private val retrofitFactory: RetrofitFactory,
|
private val retrofitFactory: RetrofitFactory,
|
||||||
private val cryptoUtils: CryptoUtils,
|
private val cryptoUtils: CryptoUtils,
|
||||||
|
private val marketService: MarketService, // 市场信息服务
|
||||||
private val telegramNotificationService: TelegramNotificationService? = null // 可选,避免循环依赖
|
private val telegramNotificationService: TelegramNotificationService? = null // 可选,避免循环依赖
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -269,11 +270,8 @@ open class CopyOrderTrackingService(
|
|||||||
var marketTitle: String? = null
|
var marketTitle: String? = null
|
||||||
if (copyTrading.keywordFilterMode != null && copyTrading.keywordFilterMode != "DISABLED") {
|
if (copyTrading.keywordFilterMode != null && copyTrading.keywordFilterMode != "DISABLED") {
|
||||||
try {
|
try {
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
val market = marketService.getMarket(trade.market)
|
||||||
val marketResponse = gammaApi.listMarkets(conditionIds = listOf(trade.market))
|
marketTitle = market?.title
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketTitle = marketResponse.body()!!.firstOrNull()?.question
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.warn("获取市场标题失败(关键字过滤需要): ${e.message}", e)
|
logger.warn("获取市场标题失败(关键字过滤需要): ${e.message}", e)
|
||||||
}
|
}
|
||||||
@@ -300,23 +298,9 @@ open class CopyOrderTrackingService(
|
|||||||
notificationScope.launch {
|
notificationScope.launch {
|
||||||
try {
|
try {
|
||||||
// 获取市场信息(标题和slug)
|
// 获取市场信息(标题和slug)
|
||||||
val marketInfo = withContext(Dispatchers.IO) {
|
val market = marketService.getMarket(trade.market)
|
||||||
try {
|
val marketTitle = market?.title ?: trade.market
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
val marketSlug = market?.slug // 显示用的 slug
|
||||||
val marketResponse = gammaApi.listMarkets(conditionIds = listOf(trade.market))
|
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketResponse.body()!!.firstOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.warn("获取市场信息失败: ${e.message}", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val marketTitle = marketInfo?.question ?: trade.market
|
|
||||||
val marketSlug = marketInfo?.slug // 显示用的 slug
|
|
||||||
|
|
||||||
// 从过滤结果中提取 filterType
|
// 从过滤结果中提取 filterType
|
||||||
val filterType = extractFilterType(filterResult.status, filterResult.reason)
|
val filterType = extractFilterType(filterResult.status, filterResult.reason)
|
||||||
@@ -365,7 +349,7 @@ open class CopyOrderTrackingService(
|
|||||||
telegramNotificationService?.sendOrderFilteredNotification(
|
telegramNotificationService?.sendOrderFilteredNotification(
|
||||||
marketTitle = marketTitle,
|
marketTitle = marketTitle,
|
||||||
marketId = trade.market,
|
marketId = trade.market,
|
||||||
marketSlug = marketInfo.getEventSlug(), // 跳转用的 slug
|
marketSlug = marketSlug,
|
||||||
side = "BUY",
|
side = "BUY",
|
||||||
outcome = trade.outcome,
|
outcome = trade.outcome,
|
||||||
price = trade.price,
|
price = trade.price,
|
||||||
@@ -571,23 +555,9 @@ open class CopyOrderTrackingService(
|
|||||||
notificationScope.launch {
|
notificationScope.launch {
|
||||||
try {
|
try {
|
||||||
// 获取市场信息(标题和slug)
|
// 获取市场信息(标题和slug)
|
||||||
val marketInfo = withContext(Dispatchers.IO) {
|
val market = marketService.getMarket(trade.market)
|
||||||
try {
|
val marketTitle = market?.title ?: trade.market
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
val marketSlug = market?.eventSlug // 跳转用的 slug
|
||||||
val marketResponse =
|
|
||||||
gammaApi.listMarkets(conditionIds = listOf(trade.market))
|
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketResponse.body()!!.firstOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.warn("获取市场信息失败: ${e.message}", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val marketTitle = marketInfo?.question ?: trade.market
|
|
||||||
|
|
||||||
// 获取当前语言设置(从 LocaleContextHolder)
|
// 获取当前语言设置(从 LocaleContextHolder)
|
||||||
val locale = try {
|
val locale = try {
|
||||||
@@ -599,7 +569,7 @@ open class CopyOrderTrackingService(
|
|||||||
telegramNotificationService?.sendOrderFailureNotification(
|
telegramNotificationService?.sendOrderFailureNotification(
|
||||||
marketTitle = marketTitle,
|
marketTitle = marketTitle,
|
||||||
marketId = trade.market,
|
marketId = trade.market,
|
||||||
marketSlug = marketInfo.getEventSlug(), // 跳转用的 slug
|
marketSlug = marketSlug,
|
||||||
side = "BUY",
|
side = "BUY",
|
||||||
outcome = null, // 失败时可能没有 outcome
|
outcome = null, // 失败时可能没有 outcome
|
||||||
price = buyPrice.toString(),
|
price = buyPrice.toString(),
|
||||||
|
|||||||
+8
-35
@@ -3,12 +3,12 @@ package com.wrbug.polymarketbot.service.copytrading.statistics
|
|||||||
import com.wrbug.polymarketbot.api.PolymarketClobApi
|
import com.wrbug.polymarketbot.api.PolymarketClobApi
|
||||||
import com.wrbug.polymarketbot.entity.*
|
import com.wrbug.polymarketbot.entity.*
|
||||||
import com.wrbug.polymarketbot.repository.*
|
import com.wrbug.polymarketbot.repository.*
|
||||||
|
import com.wrbug.polymarketbot.service.common.MarketService
|
||||||
import com.wrbug.polymarketbot.service.system.TelegramNotificationService
|
import com.wrbug.polymarketbot.service.system.TelegramNotificationService
|
||||||
import com.wrbug.polymarketbot.util.RetrofitFactory
|
import com.wrbug.polymarketbot.util.RetrofitFactory
|
||||||
import com.wrbug.polymarketbot.util.CryptoUtils
|
import com.wrbug.polymarketbot.util.CryptoUtils
|
||||||
import com.wrbug.polymarketbot.util.toSafeBigDecimal
|
import com.wrbug.polymarketbot.util.toSafeBigDecimal
|
||||||
import com.wrbug.polymarketbot.util.multi
|
import com.wrbug.polymarketbot.util.multi
|
||||||
import com.wrbug.polymarketbot.util.getEventSlug
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent
|
import org.springframework.boot.context.event.ApplicationReadyEvent
|
||||||
@@ -34,6 +34,7 @@ class OrderStatusUpdateService(
|
|||||||
private val retrofitFactory: RetrofitFactory,
|
private val retrofitFactory: RetrofitFactory,
|
||||||
private val cryptoUtils: CryptoUtils,
|
private val cryptoUtils: CryptoUtils,
|
||||||
private val trackingService: CopyOrderTrackingService,
|
private val trackingService: CopyOrderTrackingService,
|
||||||
|
private val marketService: MarketService, // 市场信息服务
|
||||||
private val telegramNotificationService: TelegramNotificationService?
|
private val telegramNotificationService: TelegramNotificationService?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -715,22 +716,8 @@ class OrderStatusUpdateService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取市场信息
|
// 获取市场信息
|
||||||
val marketInfo = withContext(Dispatchers.IO) {
|
val market = marketService.getMarket(order.marketId)
|
||||||
try {
|
val marketTitle = market?.title ?: order.marketId
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
|
||||||
val marketResponse = gammaApi.listMarkets(conditionIds = listOf(order.marketId))
|
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketResponse.body()!!.firstOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.warn("获取市场信息失败: ${e.message}", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val marketTitle = marketInfo?.question ?: order.marketId
|
|
||||||
|
|
||||||
// 获取 Leader 和跟单配置信息
|
// 获取 Leader 和跟单配置信息
|
||||||
val leader = leaderRepository.findById(order.leaderId).orElse(null)
|
val leader = leaderRepository.findById(order.leaderId).orElse(null)
|
||||||
@@ -761,7 +748,7 @@ class OrderStatusUpdateService(
|
|||||||
orderId = order.buyOrderId,
|
orderId = order.buyOrderId,
|
||||||
marketTitle = marketTitle,
|
marketTitle = marketTitle,
|
||||||
marketId = order.marketId,
|
marketId = order.marketId,
|
||||||
marketSlug = marketInfo.getEventSlug(), // 跳转用的 slug
|
marketSlug = market?.eventSlug, // 跳转用的 slug
|
||||||
side = "BUY",
|
side = "BUY",
|
||||||
price = actualPrice ?: order.price.toString(), // 使用实际价格或临时价格
|
price = actualPrice ?: order.price.toString(), // 使用实际价格或临时价格
|
||||||
size = actualSize ?: order.quantity.toString(), // 使用实际数量或临时数量
|
size = actualSize ?: order.quantity.toString(), // 使用实际数量或临时数量
|
||||||
@@ -819,22 +806,8 @@ class OrderStatusUpdateService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取市场信息
|
// 获取市场信息
|
||||||
val marketInfo = withContext(Dispatchers.IO) {
|
val market = marketService.getMarket(record.marketId)
|
||||||
try {
|
val marketTitle = market?.title ?: record.marketId
|
||||||
val gammaApi = retrofitFactory.createGammaApi()
|
|
||||||
val marketResponse = gammaApi.listMarkets(conditionIds = listOf(record.marketId))
|
|
||||||
if (marketResponse.isSuccessful && marketResponse.body() != null) {
|
|
||||||
marketResponse.body()!!.firstOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.warn("获取市场信息失败: ${e.message}", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val marketTitle = marketInfo?.question ?: record.marketId
|
|
||||||
|
|
||||||
// 获取 Leader 和跟单配置信息
|
// 获取 Leader 和跟单配置信息
|
||||||
val leader = leaderRepository.findById(finalCopyTrading.leaderId).orElse(null)
|
val leader = leaderRepository.findById(finalCopyTrading.leaderId).orElse(null)
|
||||||
@@ -865,7 +838,7 @@ class OrderStatusUpdateService(
|
|||||||
orderId = record.sellOrderId,
|
orderId = record.sellOrderId,
|
||||||
marketTitle = marketTitle,
|
marketTitle = marketTitle,
|
||||||
marketId = record.marketId,
|
marketId = record.marketId,
|
||||||
marketSlug = marketInfo.getEventSlug(), // 跳转用的 slug
|
marketSlug = market?.eventSlug, // 跳转用的 slug
|
||||||
side = "SELL",
|
side = "SELL",
|
||||||
price = actualPrice ?: record.sellPrice.toString(), // 使用实际价格或临时价格
|
price = actualPrice ?: record.sellPrice.toString(), // 使用实际价格或临时价格
|
||||||
size = actualSize ?: record.totalMatchedQuantity.toString(), // 使用实际数量或临时数量
|
size = actualSize ?: record.totalMatchedQuantity.toString(), // 使用实际数量或临时数量
|
||||||
|
|||||||
Reference in New Issue
Block a user