失败记录日志

This commit is contained in:
wuweihua
2026-10-21 10:45:04 +08:00
parent dd2efef456
commit 36837f94bf
3 changed files with 102 additions and 6 deletions
@@ -828,7 +828,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
String taskId = IdUtils.fastSimpleUUID(); String taskId = IdUtils.fastSimpleUUID();
localRebillAsyncRunner.put(taskId, BatchAddIncomeBillFeeTask.STATUS_PENDING, 0, "queued", null, localRebillAsyncRunner.put(taskId, BatchAddIncomeBillFeeTask.STATUS_PENDING, 0, "queued", null,
billIds.size(), 0, 0); billIds.size(), 0, 0);
localRebillAsyncRunner.run(taskId, billIds); // One ES op-log per batch on finish (LOCAL_REBILL_DONE); fail orders go into detail.failDetails.
localRebillAsyncRunner.run(taskId, billIds, request);
return taskId; return taskId;
} }
@@ -1,7 +1,10 @@
package com.bms.price.task; package com.bms.price.task;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -20,6 +23,12 @@ import com.bms.common.core.redis.RedisCache;
import com.bms.common.utils.StringUtils; import com.bms.common.utils.StringUtils;
import com.bms.price.config.BillingProperties; import com.bms.price.config.BillingProperties;
import com.bms.price.domain.BatchAddIncomeBillFeeTask; import com.bms.price.domain.BatchAddIncomeBillFeeTask;
import com.bms.price.domain.PrcOrderBill;
import com.bms.price.domain.vo.LocalRebillRequest;
import com.bms.price.mapper.PrcOrderBillMapper;
import com.bms.price.search.EsBizLogSupport;
import com.bms.price.search.IBillSearchStore;
import com.bms.price.search.TabOrderSyncEsLog;
import com.bms.price.service.IPrcOrderBillService; import com.bms.price.service.IPrcOrderBillService;
/** /**
@@ -37,6 +46,7 @@ public class PrcOrderBillLocalRebillAsyncRunner
public static final int PAGE_SIZE = 500; public static final int PAGE_SIZE = 500;
public static final int MIN_THREADS = 2; public static final int MIN_THREADS = 2;
public static final int MAX_THREADS = 16; public static final int MAX_THREADS = 16;
private static final int FAIL_DETAIL_MAX = 200;
@Autowired @Autowired
@Lazy @Lazy
@@ -48,13 +58,26 @@ public class PrcOrderBillLocalRebillAsyncRunner
@Autowired @Autowired
private BillingProperties billingProperties; private BillingProperties billingProperties;
@Autowired
private IBillSearchStore billSearchStore;
@Autowired
private PrcOrderBillMapper orderBillMapper;
@Async("threadPoolTaskExecutor") @Async("threadPoolTaskExecutor")
public void run(String taskId, List<String> billIds) public void run(String taskId, List<String> billIds)
{
run(taskId, billIds, null);
}
@Async("threadPoolTaskExecutor")
public void run(String taskId, List<String> billIds, LocalRebillRequest request)
{ {
int total = billIds == null ? 0 : billIds.size(); int total = billIds == null ? 0 : billIds.size();
AtomicInteger success = new AtomicInteger(0); AtomicInteger success = new AtomicInteger(0);
AtomicInteger fail = new AtomicInteger(0); AtomicInteger fail = new AtomicInteger(0);
StringBuilder failTips = new StringBuilder(); StringBuilder failTips = new StringBuilder();
List<Map<String, Object>> failDetails = Collections.synchronizedList(new ArrayList<Map<String, Object>>());
int threads = clampThreads(billingProperties == null ? null : billingProperties.getOrderSourceSyncThreads()); int threads = clampThreads(billingProperties == null ? null : billingProperties.getOrderSourceSyncThreads());
ExecutorService pool = newWorkerPool(threads, "local-rebill"); ExecutorService pool = newWorkerPool(threads, "local-rebill");
try try
@@ -63,6 +86,7 @@ public class PrcOrderBillLocalRebillAsyncRunner
if (total == 0) if (total == 0)
{ {
put(taskId, BatchAddIncomeBillFeeTask.STATUS_FAIL, 100, "failed", "no bills", 0, 0, 0); put(taskId, BatchAddIncomeBillFeeTask.STATUS_FAIL, 100, "failed", "no bills", 0, 0, 0);
saveDoneLog(taskId, request, total, 0, 0, threads, failDetails, "FAIL", "no bills");
return; return;
} }
int processed = 0; int processed = 0;
@@ -85,7 +109,9 @@ public class PrcOrderBillLocalRebillAsyncRunner
{ {
fail.incrementAndGet(); fail.incrementAndGet();
appendFail(failTips, one, e); appendFail(failTips, one, e);
log.warn("local rebill failed taskId={} billId={}", taskId, one, e); collectFailDetail(failDetails, one, e);
log.warn("local rebill failed taskId={} billId={} msg={}",
taskId, one, e.getMessage());
return Boolean.FALSE; return Boolean.FALSE;
} }
}); });
@@ -98,17 +124,23 @@ public class PrcOrderBillLocalRebillAsyncRunner
null, total, success.get(), fail.get()); null, total, success.get(), fail.get());
} }
String msg = "success=" + success.get() + ", fail=" + fail.get(); String msg = "success=" + success.get() + ", fail=" + fail.get();
put(taskId, BatchAddIncomeBillFeeTask.STATUS_SUCCESS, 100, msg, String err = fail.get() > 0 && failTips.length() > 0 ? failTips.toString() : null;
fail.get() > 0 && failTips.length() > 0 ? failTips.toString() : null, put(taskId, BatchAddIncomeBillFeeTask.STATUS_SUCCESS, 100, msg, err,
total, success.get(), fail.get()); total, success.get(), fail.get());
String doneStatus = fail.get() > 0 ? EsBizLogSupport.STATUS_FAIL : EsBizLogSupport.STATUS_SUCCESS;
String doneErr = fail.get() > 0 ? ("fail=" + fail.get() + ", ok=" + success.get()) : null;
saveDoneLog(taskId, request, total, success.get(), fail.get(), threads, failDetails, doneStatus, doneErr);
log.info("local rebill done taskId={} total={} success={} fail={} threads={} pageSize={}", log.info("local rebill done taskId={} total={} success={} fail={} threads={} pageSize={}",
taskId, total, success.get(), fail.get(), threads, PAGE_SIZE); taskId, total, success.get(), fail.get(), threads, PAGE_SIZE);
} }
catch (Exception e) catch (Exception e)
{ {
log.error("local rebill aborted taskId={}", taskId, e); log.error("local rebill aborted taskId={}", taskId, e);
put(taskId, BatchAddIncomeBillFeeTask.STATUS_FAIL, 100, "failed", errorMessage(e), String msg = errorMessage(e);
put(taskId, BatchAddIncomeBillFeeTask.STATUS_FAIL, 100, "failed", msg,
total, success.get(), fail.get()); total, success.get(), fail.get());
saveDoneLog(taskId, request, total, success.get(), fail.get(), threads, failDetails,
EsBizLogSupport.STATUS_FAIL, msg);
} }
finally finally
{ {
@@ -116,6 +148,64 @@ public class PrcOrderBillLocalRebillAsyncRunner
} }
} }
private void saveDoneLog(String taskId, LocalRebillRequest request, int total, int ok, int fail,
int threads, List<Map<String, Object>> failDetails, String status, String errorMessage)
{
Map<String, Object> resp = new LinkedHashMap<String, Object>();
resp.put("taskId", taskId);
resp.put("total", Integer.valueOf(total));
resp.put("ok", Integer.valueOf(ok));
resp.put("fail", Integer.valueOf(fail));
resp.put("success", Integer.valueOf(ok));
resp.put("threads", Integer.valueOf(threads));
resp.put("pageSize", Integer.valueOf(PAGE_SIZE));
if (failDetails != null && !failDetails.isEmpty())
{
resp.put("failDetails", new ArrayList<Map<String, Object>>(failDetails));
}
TabOrderSyncEsLog.save(billSearchStore, taskId, "LOCAL_REBILL_DONE", request, resp, status, errorMessage);
}
private void collectFailDetail(List<Map<String, Object>> failDetails, String billId, Exception e)
{
if (failDetails == null)
{
return;
}
synchronized (failDetails)
{
if (failDetails.size() >= FAIL_DETAIL_MAX)
{
return;
}
Map<String, Object> item = new LinkedHashMap<String, Object>();
item.put("billId", billId);
String orderNo = null;
String transferNo = null;
String trackingNo = null;
try
{
PrcOrderBill bill = orderBillMapper == null || StringUtils.isEmpty(billId)
? null : orderBillMapper.selectPrcOrderBillById(billId.trim());
if (bill != null)
{
orderNo = bill.getOrderNo();
transferNo = bill.getTransferNo();
trackingNo = bill.getTrackingNo();
}
}
catch (Exception ignore)
{
// detail enrichment is best-effort
}
item.put("orderId", StringUtils.isEmpty(orderNo) ? billId : orderNo);
item.put("transferOrderId", transferNo);
item.put("trackingNo", trackingNo);
item.put("errorMessage", errorMessage(e));
failDetails.add(item);
}
}
public void put(String taskId, String status, int percent, String message, String error, public void put(String taskId, String status, int percent, String message, String error,
int total, int success, int fail) int total, int success, int fail)
{ {
@@ -39,8 +39,9 @@
<div class="json-panel__head"><span>失败明细(共 {{ failRows.length }} 单)</span></div> <div class="json-panel__head"><span>失败明细(共 {{ failRows.length }} 单)</span></div>
<el-table :data="failRows" border size="small" max-height="280" class="fail-table"> <el-table :data="failRows" border size="small" max-height="280" class="fail-table">
<el-table-column label="订单号" prop="orderId" min-width="160" show-overflow-tooltip /> <el-table-column label="订单号" prop="orderId" min-width="160" show-overflow-tooltip />
<el-table-column label="运单号" prop="trackingNo" min-width="140" show-overflow-tooltip />
<el-table-column label="转单号" prop="transferOrderId" min-width="140" show-overflow-tooltip /> <el-table-column label="转单号" prop="transferOrderId" min-width="140" show-overflow-tooltip />
<el-table-column label="错误信息" prop="errorMessage" min-width="220" show-overflow-tooltip /> <el-table-column label="错误信息" prop="errorMessage" min-width="240" show-overflow-tooltip />
</el-table> </el-table>
</div> </div>
<div class="json-panel"> <div class="json-panel">
@@ -113,6 +114,10 @@ function actionLabel(row) {
if (action === 'COMPARE_DONE') { if (action === 'COMPARE_DONE') {
return row.status === 'FAIL' ? '比对完成(失败)' : '比对完成' return row.status === 'FAIL' ? '比对完成(失败)' : '比对完成'
} }
if (action === 'LOCAL_REBILL') return '本地重新计费'
if (action === 'LOCAL_REBILL_DONE') {
return row.status === 'FAIL' ? '本地重新计费完成(有失败)' : '本地重新计费完成'
}
return action || '-' return action || '-'
} }