fix(selfop): isolate inventory paging and bound unstable scan retries
This commit is contained in:
+2
@@ -53,6 +53,8 @@ public class SelfopAnalyticsProperties {
|
||||
private int leaseSeconds = 180;
|
||||
private int maxAttempts = 5;
|
||||
private int pageSize = 100;
|
||||
/** Inventory supports larger pages independently of the outbound list limit. */
|
||||
private int inventoryPageSize = 1000;
|
||||
private int applyBatchSize = 100;
|
||||
private Map<String, Warehouse> warehouses = new LinkedHashMap<>();
|
||||
@Data
|
||||
|
||||
+4
-2
@@ -25,12 +25,14 @@ public class SelfopInventoryCollector {
|
||||
}
|
||||
public boolean collect(SelfopSyncTask task,SelfopSyncRun run,SelfopLeaseService.Lease lease){
|
||||
SelfopCollectionPolicy.requireBusiness(task);SelfopCollectionPolicy.requireBusiness(run);
|
||||
int pageSize=config.getInventoryPageSize();
|
||||
require(pageSize>=1&&pageSize<=1000,"SELFOP_INVENTORY_PAGE_SIZE_INVALID");
|
||||
var manifest=task.getRoutingManifestJson()==null?new SelfopRoutingManifest():read(task.getRoutingManifestJson(),SelfopRoutingManifest.class);
|
||||
var budget=new SelfopBudget(config.getRequestBudget(),config.getTimeBudgetSeconds());
|
||||
while(!manifest.isDirectoryComplete()){
|
||||
if(!budget.take()){taskService.yield(task.getId(),run.getId(),lease);return false;}
|
||||
leases.renew(lease);var page=client.inventory(SelfopRequestContext.forTask(task,run,config),task.getWarehouseCode(),manifest.getNextPage(),config.getPageSize());
|
||||
require(page.current()==manifest.getNextPage()&&page.size()==config.getPageSize(),"SELFOP_PAGE_MISMATCH");
|
||||
leases.renew(lease);var page=client.inventory(SelfopRequestContext.forTask(task,run,config),task.getWarehouseCode(),manifest.getNextPage(),pageSize);
|
||||
require(page.current()==manifest.getNextPage()&&page.size()==pageSize,"SELFOP_PAGE_MISMATCH");
|
||||
require(page.total()!=null&&page.pages()!=null,"SELFOP_PAGE_METADATA_MISSING");
|
||||
if(manifest.getTotal()==null){manifest.setTotal(page.total());manifest.setPages(page.pages());}
|
||||
require(Objects.equals(manifest.getTotal(),page.total())&&Objects.equals(manifest.getPages(),page.pages()),"SELFOP_PAGE_TOTAL_CHANGED");
|
||||
|
||||
+8
-2
@@ -198,10 +198,15 @@ public class SelfopTaskService {
|
||||
run.setErrorMessage("自营同步失败,需核对运行记录");run.setFinishedAtUtc(now);run.setUpdatedAt(now);runs.updateById(run);
|
||||
// A yielded execution is not a failed request; finite failures are counted separately.
|
||||
long failures=runs.selectCount(new QueryWrapper<SelfopSyncRun>().eq("task_id",taskId).eq("status","FAILED"));
|
||||
if(task.getBusinessRootTaskId()!=null&&continuousBusinessRoot(tasks.selectById(task.getBusinessRootTaskId())))retryable=false;
|
||||
boolean inventory=task.getScopeId()!=null&&"INVENTORY".equals(scopes.selectById(task.getScopeId()).getDataFamily());
|
||||
if(task.getBusinessRootTaskId()!=null&&continuousBusinessRoot(tasks.selectById(task.getBusinessRootTaskId()))) {
|
||||
// A completed response with an unstable inventory scan can be read again from page one.
|
||||
// Authentication, rate limits, uncertain transport results and other families retain their stop policy.
|
||||
retryable=retryable&&inventory&&Set.of("SELFOP_STOCK_DUPLICATE","SELFOP_STOCK_COUNT_MISMATCH","SELFOP_PAGE_TOTAL_CHANGED").contains(code);
|
||||
}
|
||||
task.setStatus(retryable&&failures<config.getMaxAttempts()?"RETRY_WAIT":"DEAD");
|
||||
if("APPLYING".equals(task.getApplyState())) task.setApplyState("BLOCKED");
|
||||
if(task.getScopeId()!=null&&"INVENTORY".equals(scopes.selectById(task.getScopeId()).getDataFamily())) {
|
||||
if(inventory) {
|
||||
task.setRoutingManifestJson(null);
|
||||
tasks.update(null,new UpdateWrapper<SelfopSyncTask>().eq("id",taskId).set("routing_manifest_json",null));
|
||||
}
|
||||
@@ -210,6 +215,7 @@ public class SelfopTaskService {
|
||||
tasks.update(null,new UpdateWrapper<SelfopSyncTask>().eq("id",taskId).set("routing_manifest_json",null));
|
||||
}
|
||||
task.setNextRetryAtUtc("DEAD".equals(task.getStatus())?null:now.plusSeconds(Math.min(3600,5L<<Math.min(9,(int)failures))));task.setUpdatedAt(now);tasks.updateById(task);
|
||||
if("DEAD".equals(task.getStatus()))tasks.update(null,new UpdateWrapper<SelfopSyncTask>().eq("id",taskId).set("next_retry_at_utc",null));
|
||||
}
|
||||
@Transactional(noRollbackFor=BusinessSessionStoppedException.class)
|
||||
public SelfopSyncTask retry(long id,String requestKey,String operator,String reason) {
|
||||
|
||||
Reference in New Issue
Block a user