同步计费优化

This commit is contained in:
luojiaquan
2026-10-16 10:59:59 +08:00
parent 2689138b6a
commit 132688b9cf
10 changed files with 305 additions and 109 deletions
@@ -43,11 +43,14 @@ public class TabOrderSyncAsyncRunner
public static final String CACHE_KEY_PREFIX = "billing:orderSource:sync:";
public static final int TTL_MINUTES = 120;
public static final int DEFAULT_BATCH = 50;
/** 每页拉取的订单行数:行内直接带 Oracle 全行数据,单页大些可减少分页往返。 */
public static final int DEFAULT_BATCH = 100;
public static final int MIN_BATCH = 20;
public static final int MAX_BATCH = 200;
public static final int MIN_THREADS = 2;
public static final int MAX_THREADS = 16;
/** 进度写入 Redis 的最小间隔(条数),避免每单一次 Redis SET。 */
private static final int PROGRESS_REPORT_EVERY = 10;
@Autowired
private TabOrderMonitorService tabOrderMonitorService;
@@ -97,7 +100,7 @@ public class TabOrderSyncAsyncRunner
int pageNum = 1;
while (true)
{
List<TabOrderMonitorVo> rows;
List<com.bms.price.oracle.TabOrderRow> rows;
if (keys != null)
{
int from = (pageNum - 1) * batch;
@@ -105,12 +108,12 @@ public class TabOrderSyncAsyncRunner
{
break;
}
rows = tabOrderMonitorService.selectPageByKeys(
rows = tabOrderMonitorService.selectRowsByKeys(
keys.subList(from, Math.min(from + batch, keys.size())));
}
else
{
rows = tabOrderMonitorService.selectPage(query, pageNum, batch);
rows = tabOrderMonitorService.selectRownumRows(query, pageNum, batch);
}
if (rows == null || rows.isEmpty())
{
@@ -122,9 +125,9 @@ public class TabOrderSyncAsyncRunner
total, processed.get(), ok.get(), fail.get(), null);
List<Callable<Boolean>> jobs = new ArrayList<Callable<Boolean>>(rows.size());
for (TabOrderMonitorVo row : rows)
for (com.bms.price.oracle.TabOrderRow row : rows)
{
final TabOrderMonitorVo one = row;
final com.bms.price.oracle.TabOrderRow one = row;
jobs.add(() -> {
boolean success = syncOne(one, failDetails);
if (success)
@@ -136,10 +139,14 @@ public class TabOrderSyncAsyncRunner
fail.incrementAndGet();
}
int done = processed.incrementAndGet();
int percent = Math.min(99, (int) ((done * 100L) / Math.max(1, total)));
put(asyncTaskId, PrcBillingTaskRetryTask.STATUS_RUNNING, percent,
"processing " + done + "/" + total,
total, done, ok.get(), fail.get(), null);
// 降频写 Redis(每 10 条或最后一条),轮询端 1.5s 一次无需更细粒度
if (done % PROGRESS_REPORT_EVERY == 0 || done >= total)
{
int percent = Math.min(99, (int) ((done * 100L) / Math.max(1, total)));
put(asyncTaskId, PrcBillingTaskRetryTask.STATUS_RUNNING, percent,
"processing " + done + "/" + total,
total, done, ok.get(), fail.get(), null);
}
return Boolean.valueOf(success);
});
}
@@ -196,6 +203,25 @@ public class TabOrderSyncAsyncRunner
* @param billType optional PENDING/REBILL/REFUND; null = auto PENDING/REBILL
*/
public Map<String, Object> syncRowsParallel(List<TabOrderMonitorVo> rows, String billType)
{
if (rows == null || rows.isEmpty())
{
return syncRowsParallelRows(java.util.Collections.<com.bms.price.oracle.TabOrderRow>emptyList(), billType);
}
List<com.bms.price.oracle.TabOrderRow> wrapped =
new ArrayList<com.bms.price.oracle.TabOrderRow>(rows.size());
for (TabOrderMonitorVo vo : rows)
{
wrapped.add(new com.bms.price.oracle.TabOrderRow(vo, null));
}
return syncRowsParallelRows(wrapped, billType);
}
/**
* Sync or refund selected rows carrying the upstream Oracle full row (skip re-query).
* @param billType optional PENDING/REBILL/REFUND; null = auto PENDING/REBILL
*/
public Map<String, Object> syncRowsParallelRows(List<com.bms.price.oracle.TabOrderRow> rows, String billType)
{
Map<String, Object> data = new HashMap<String, Object>();
List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();
@@ -215,16 +241,18 @@ public class TabOrderSyncAsyncRunner
try
{
List<Callable<Map<String, Object>>> jobs = new ArrayList<Callable<Map<String, Object>>>(rows.size());
for (TabOrderMonitorVo row : rows)
for (com.bms.price.oracle.TabOrderRow row : rows)
{
final TabOrderMonitorVo one = row;
final com.bms.price.oracle.TabOrderRow one = row;
jobs.add(() -> {
Map<String, Object> item = new HashMap<String, Object>();
item.put("orderId", one == null ? null : one.getOrderId());
item.put("transferOrderId", one == null ? null : one.getTransferOrderId());
TabOrderMonitorVo vo = one == null ? null : one.getVo();
item.put("orderId", vo == null ? null : vo.getOrderId());
item.put("transferOrderId", vo == null ? null : vo.getTransferOrderId());
try
{
PrcBillingTask task = billingTaskService.submitAndProcess(toSubmit(one, fixedBillType));
PrcBillingTask task = billingTaskService.submitAndProcess(
toSubmit(vo, fixedBillType), one == null ? null : one.getRaw());
item.put("successStatus", task == null ? null : task.getSuccessStatus());
item.put("errorMessage", task == null ? null : task.getErrorMessage());
item.put("billType", task == null ? fixedBillType : task.getBillType());
@@ -280,26 +308,28 @@ public class TabOrderSyncAsyncRunner
return data;
}
private boolean syncOne(TabOrderMonitorVo row, List<Map<String, Object>> failDetails)
private boolean syncOne(com.bms.price.oracle.TabOrderRow row, List<Map<String, Object>> failDetails)
{
TabOrderMonitorVo vo = row == null ? null : row.getVo();
try
{
PrcBillingTask task = billingTaskService.submitAndProcess(toSubmit(row));
PrcBillingTask task = billingTaskService.submitAndProcess(
toSubmit(vo), row == null ? null : row.getRaw());
boolean success = task != null
&& BillTaskSuccessStatus.SUCCESS.getCode().equals(task.getSuccessStatus());
if (!success)
{
collectFailDetail(failDetails, row, task, null);
collectFailDetail(failDetails, vo, task, null);
}
return success;
}
catch (RuntimeException e)
{
log.warn("orderSource sync failed orderId={} transfer={} msg={}",
row == null ? null : row.getOrderId(),
row == null ? null : row.getTransferOrderId(),
vo == null ? null : vo.getOrderId(),
vo == null ? null : vo.getTransferOrderId(),
e.getMessage());
collectFailDetail(failDetails, row, null, e.getMessage());
collectFailDetail(failDetails, vo, null, e.getMessage());
return false;
}
}
@@ -446,7 +476,7 @@ public class TabOrderSyncAsyncRunner
public static int clampThreads(Integer threads)
{
int n = threads == null || threads.intValue() <= 0 ? 8 : threads.intValue();
int n = threads == null || threads.intValue() <= 0 ? 16 : threads.intValue();
if (n < MIN_THREADS)
{
return MIN_THREADS;