优化订单状态更新和统计服务

1. 订单详情为 null 且已部分卖出的订单超时清理
   - 新增 PARTIAL_SOLD_CLEANUP_WINDOW_MS 常量(1小时)
   - 超过1小时无法获取详情的已部分卖出订单自动清理
   - 避免无效订单长期占用数据库空间

2. 优化买入订单分组排序逻辑
   - 按最近买入订单时间排序,提升用户体验
   - 修复日志中的错误描述(卖出订单列表)

3. 代码格式化优化
This commit is contained in:
WrBug
2026-01-15 02:28:11 +08:00
parent 5d2cf945f3
commit 5f44a0ca20
2 changed files with 62 additions and 21 deletions
@@ -672,7 +672,15 @@ class CopyTradingStatisticsService(
stats = stats, stats = stats,
orders = orderDtos as List<Any> orders = orderDtos as List<Any>
) )
}.sortedByDescending { it.stats.count } }.sortedByDescending { group ->
// 找出该市场最近的买入订单时间
group.orders.mapNotNull { order ->
when (order) {
is BuyOrderInfo -> order.createdAt
else -> null
}
}.maxOrNull() ?: 0L
}
// 5. 分页 // 5. 分页
val page = (request.page ?: 1) val page = (request.page ?: 1)
@@ -692,7 +700,7 @@ class CopyTradingStatisticsService(
Result.success(response) Result.success(response)
} catch (e: Exception) { } catch (e: Exception) {
logger.error("获取按市场分组的买入订单列表失败: copyTradingId=${request.copyTradingId}", e) logger.error("获取按市场分组的卖出订单列表失败: copyTradingId=${request.copyTradingId}", e)
Result.failure(e) Result.failure(e)
} }
} }
@@ -49,6 +49,9 @@ class OrderStatusUpdateService(
// 订单详情为 null 的重试时间窗口(1分钟) // 订单详情为 null 的重试时间窗口(1分钟)
private val ORDER_NULL_RETRY_WINDOW_MS = 60000L private val ORDER_NULL_RETRY_WINDOW_MS = 60000L
// 订单详情为 null 但已部分卖出的清理时间窗口(1小时)
private val PARTIAL_SOLD_CLEANUP_WINDOW_MS = 3600000L
@EventListener(ApplicationReadyEvent::class) @EventListener(ApplicationReadyEvent::class)
fun onApplicationReady() { fun onApplicationReady() {
logger.info("订单状态更新服务已启动,将每5秒轮询一次") logger.info("订单状态更新服务已启动,将每5秒轮询一次")
@@ -234,10 +237,25 @@ class OrderStatusUpdateService(
// 检查订单是否已部分卖出,如果已部分卖出则保留订单用于统计 // 检查订单是否已部分卖出,如果已部分卖出则保留订单用于统计
val hasMatchedDetails = sellMatchDetailRepository.findByTrackingId(order.id!!).isNotEmpty() val hasMatchedDetails = sellMatchDetailRepository.findByTrackingId(order.id!!).isNotEmpty()
if (hasMatchedDetails || order.matchedQuantity > BigDecimal.ZERO) { if (hasMatchedDetails || order.matchedQuantity > BigDecimal.ZERO) {
logger.debug("订单详情为 null 但已部分卖出,保留订单用于统计: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, matchedQuantity=${order.matchedQuantity}") // 检查是否超过清理时间窗口(1小时)
// 清除缓存,下次重新检测 val orderAge = currentTime - order.createdAt
orderNullDetectionTime.remove(order.buyOrderId) if (orderAge >= PARTIAL_SOLD_CLEANUP_WINDOW_MS) {
continue logger.warn("订单详情为 null 且已部分卖出,但超过清理时间窗口,删除本地订单: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, matchedQuantity=${order.matchedQuantity}, 已等待=${orderAge / 1000}s")
try {
copyOrderTrackingRepository.deleteById(order.id!!)
logger.info("已删除本地订单(超时清理): orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}")
// 清除缓存
orderNullDetectionTime.remove(order.buyOrderId)
} catch (e: Exception) {
logger.error("删除本地订单失败: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, error=${e.message}", e)
}
continue
} else {
logger.debug("订单详情为 null 但已部分卖出,保留订单用于统计: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, matchedQuantity=${order.matchedQuantity}, 已等待=${orderAge / 1000}s")
// 清除缓存,下次重新检测
orderNullDetectionTime.remove(order.buyOrderId)
continue
}
} }
// 检查是否超过重试时间窗口 // 检查是否超过重试时间窗口
@@ -645,10 +663,25 @@ class OrderStatusUpdateService(
// 检查订单是否已部分卖出,如果已部分卖出则保留订单用于统计 // 检查订单是否已部分卖出,如果已部分卖出则保留订单用于统计
val hasMatchedDetails = sellMatchDetailRepository.findByTrackingId(order.id!!).isNotEmpty() val hasMatchedDetails = sellMatchDetailRepository.findByTrackingId(order.id!!).isNotEmpty()
if (hasMatchedDetails || order.matchedQuantity > BigDecimal.ZERO) { if (hasMatchedDetails || order.matchedQuantity > BigDecimal.ZERO) {
logger.debug("订单详情为 null 但已部分卖出,保留订单用于统计: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, matchedQuantity=${order.matchedQuantity}") // 检查是否超过清理时间窗口(1小时)
// 清除缓存,下次重新检测 val orderAge = currentTime - order.createdAt
orderNullDetectionTime.remove(order.buyOrderId) if (orderAge >= PARTIAL_SOLD_CLEANUP_WINDOW_MS) {
continue logger.warn("订单详情为 null 且已部分卖出,但超过清理时间窗口,删除本地订单: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, matchedQuantity=${order.matchedQuantity}, 已等待=${orderAge / 1000}s")
try {
copyOrderTrackingRepository.deleteById(order.id!!)
logger.info("已删除本地订单(超时清理): orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}")
// 清除缓存
orderNullDetectionTime.remove(order.buyOrderId)
} catch (e: Exception) {
logger.error("删除本地订单失败: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, error=${e.message}", e)
}
continue
} else {
logger.debug("订单详情为 null 但已部分卖出,保留订单用于统计: orderId=${order.buyOrderId}, copyOrderTrackingId=${order.id}, matchedQuantity=${order.matchedQuantity}, 已等待=${orderAge / 1000}s")
// 清除缓存,下次重新检测
orderNullDetectionTime.remove(order.buyOrderId)
continue
}
} }
// 检查是否超过重试时间窗口 // 检查是否超过重试时间窗口