修改抢单逻辑, 指定货物包的开始日期
This commit is contained in:
@@ -90,11 +90,11 @@ public class LbBuyAccountController {
|
|||||||
"根据 ids 查询 lb_buy_account,按 tenant_id 关联 lb_third_integration_config 获取 URL 与 appStr;"
|
"根据 ids 查询 lb_buy_account,按 tenant_id 关联 lb_third_integration_config 获取 URL 与 appStr;"
|
||||||
+ "各账号并发抢购(每账号一线程);accountResults 顺序与 ids 一致;同租户同货品 ID 仅允许一个账号尝试;"
|
+ "各账号并发抢购(每账号一线程);accountResults 顺序与 ids 一致;同租户同货品 ID 仅允许一个账号尝试;"
|
||||||
+ "每个账号使用 token_front 作为 hxrd 请求 Token,max_grab_count 作为最大成功抢购笔数,"
|
+ "每个账号使用 token_front 作为 hxrd 请求 Token,max_grab_count 作为最大成功抢购笔数,"
|
||||||
+ "抢购逻辑同 LbGoodsController#rushBuy")
|
+ "抢购逻辑同 LbGoodsController#rushBuy;goodsBeginTime 指定货物包开始时间,查询 lb_goods 时 updated_at 需大于此时间")
|
||||||
public ResponseEntity<Map<String, Object>> rushBuy(
|
public ResponseEntity<Map<String, Object>> rushBuy(
|
||||||
@Parameter(description = "抢单账号 ID 列表", required = true)
|
@Parameter(description = "抢单账号 ID 列表", required = true)
|
||||||
@RequestBody LbBuyAccountRushBuyRequest request) {
|
@RequestBody LbBuyAccountRushBuyRequest request) {
|
||||||
Map<String, Object> result = lbBuyAccountService.rushBuyByIds(request.getIds());
|
Map<String, Object> result = lbBuyAccountService.rushBuyByIds(request.getIds(), request.getGoodsBeginTime());
|
||||||
Boolean success = (Boolean) result.get("success");
|
Boolean success = (Boolean) result.get("success");
|
||||||
if (success != null && success) {
|
if (success != null && success) {
|
||||||
return ResponseEntity.ok(result);
|
return ResponseEntity.ok(result);
|
||||||
|
|||||||
@@ -15,4 +15,7 @@ public class LbBuyAccountRushBuyRequest {
|
|||||||
|
|
||||||
@Schema(description = "抢单账号主键 ID 列表(lb_buy_account.id)", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "抢单账号主键 ID 列表(lb_buy_account.id)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private List<String> ids;
|
private List<String> ids;
|
||||||
|
|
||||||
|
@Schema(description = "货物包开始时间,格式 yyyy-MM-dd HH:mm:ss,查询 lb_goods 时 updated_at 需大于此时间")
|
||||||
|
private String goodsBeginTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ public interface ILbBuyAccountService extends IService<LbBuyAccount> {
|
|||||||
/**
|
/**
|
||||||
* 按账号 ID 列表批量抢购:每个账号使用其 token_front 与 max_grab_count,
|
* 按账号 ID 列表批量抢购:每个账号使用其 token_front 与 max_grab_count,
|
||||||
* tenant_id 关联 lb_third_integration_config 解析 URL 与 appStr。
|
* tenant_id 关联 lb_third_integration_config 解析 URL 与 appStr。
|
||||||
|
*
|
||||||
|
* @param goodsBeginTime 货物包开始时间,格式 yyyy-MM-dd HH:mm:ss,查询 lb_goods 时 updated_at 需大于此时间
|
||||||
*/
|
*/
|
||||||
Map<String, Object> rushBuyByIds(List<String> ids);
|
Map<String, Object> rushBuyByIds(List<String> ids, String goodsBeginTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,11 +54,11 @@ public interface ILbGoodsService extends IService<LbGoods> {
|
|||||||
* @param token 失效时,按账号凭证自动登录并刷新 {@code lb_buy_account.token_front}
|
* @param token 失效时,按账号凭证自动登录并刷新 {@code lb_buy_account.token_front}
|
||||||
*/
|
*/
|
||||||
default Map<String, Object> rushBuy(String tenantId, String token, Integer maxBuyCount) {
|
default Map<String, Object> rushBuy(String tenantId, String token, Integer maxBuyCount) {
|
||||||
return rushBuy(tenantId, token, maxBuyCount, null, null, null, null, null);
|
return rushBuy(tenantId, token, maxBuyCount, null, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
default Map<String, Object> rushBuy(String tenantId, String token, Integer maxBuyCount, String rushBuyAccountLabel) {
|
default Map<String, Object> rushBuy(String tenantId, String token, Integer maxBuyCount, String rushBuyAccountLabel) {
|
||||||
return rushBuy(tenantId, token, maxBuyCount, rushBuyAccountLabel, null, null, null, null);
|
return rushBuy(tenantId, token, maxBuyCount, rushBuyAccountLabel, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
default Map<String, Object> rushBuy(
|
default Map<String, Object> rushBuy(
|
||||||
@@ -67,7 +67,7 @@ public interface ILbGoodsService extends IService<LbGoods> {
|
|||||||
Integer maxBuyCount,
|
Integer maxBuyCount,
|
||||||
String rushBuyAccountLabel,
|
String rushBuyAccountLabel,
|
||||||
LbBuyAccountRushBuyContext tokenRefreshContext) {
|
LbBuyAccountRushBuyContext tokenRefreshContext) {
|
||||||
return rushBuy(tenantId, token, maxBuyCount, rushBuyAccountLabel, tokenRefreshContext, null, null, null);
|
return rushBuy(tenantId, token, maxBuyCount, rushBuyAccountLabel, tokenRefreshContext, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> rushBuy(
|
Map<String, Object> rushBuy(
|
||||||
@@ -78,5 +78,6 @@ public interface ILbGoodsService extends IService<LbGoods> {
|
|||||||
LbBuyAccountRushBuyContext tokenRefreshContext,
|
LbBuyAccountRushBuyContext tokenRefreshContext,
|
||||||
LbRushBuyGoodsCoordinator goodsCoordinator,
|
LbRushBuyGoodsCoordinator goodsCoordinator,
|
||||||
String accountId,
|
String accountId,
|
||||||
Integer maxGrabAmount);
|
Integer maxGrabAmount,
|
||||||
|
String goodsBeginTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ public class LbBuyAccountServiceImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> rushBuyByIds(List<String> ids) {
|
public Map<String, Object> rushBuyByIds(List<String> ids, String goodsBeginTime) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
if (ids == null || ids.isEmpty()) {
|
if (ids == null || ids.isEmpty()) {
|
||||||
@@ -249,8 +249,8 @@ public class LbBuyAccountServiceImpl
|
|||||||
t.setDaemon(false);
|
t.setDaemon(false);
|
||||||
return t;
|
return t;
|
||||||
});
|
});
|
||||||
log.info("批量抢单启动,账号数={},并发线程数={}(每账号一线程),同租户同货品仅一个账号抢购",
|
log.info("批量抢单启动,账号数={},并发线程数={}(每账号一线程),同租户同货品仅一个账号抢购,goodsBeginTime={}",
|
||||||
normalizedIds.size(), poolSize);
|
normalizedIds.size(), poolSize, goodsBeginTime);
|
||||||
|
|
||||||
List<Map<String, Object>> accountResults;
|
List<Map<String, Object>> accountResults;
|
||||||
int successAccounts;
|
int successAccounts;
|
||||||
@@ -260,7 +260,7 @@ public class LbBuyAccountServiceImpl
|
|||||||
for (String id : normalizedIds) {
|
for (String id : normalizedIds) {
|
||||||
LbBuyAccount account = accountMap.get(id);
|
LbBuyAccount account = accountMap.get(id);
|
||||||
futures.add(CompletableFuture.supplyAsync(
|
futures.add(CompletableFuture.supplyAsync(
|
||||||
() -> runSingleAccountRushBuyTask(id, account, goodsCoordinator),
|
() -> runSingleAccountRushBuyTask(id, account, goodsCoordinator, goodsBeginTime),
|
||||||
executor));
|
executor));
|
||||||
}
|
}
|
||||||
CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).join();
|
CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).join();
|
||||||
@@ -309,9 +309,9 @@ public class LbBuyAccountServiceImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> runSingleAccountRushBuyTask(
|
private Map<String, Object> runSingleAccountRushBuyTask(
|
||||||
String id, LbBuyAccount account, LbRushBuyGoodsCoordinator goodsCoordinator) {
|
String id, LbBuyAccount account, LbRushBuyGoodsCoordinator goodsCoordinator, String goodsBeginTime) {
|
||||||
try {
|
try {
|
||||||
return processSingleAccountRushBuy(id, account, goodsCoordinator);
|
return processSingleAccountRushBuy(id, account, goodsCoordinator, goodsBeginTime);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("抢单账号任务执行异常,accountId={},loginAccount={},thread={}",
|
log.error("抢单账号任务执行异常,accountId={},loginAccount={},thread={}",
|
||||||
id, account != null ? account.getLoginAccount() : null,
|
id, account != null ? account.getLoginAccount() : null,
|
||||||
@@ -340,7 +340,7 @@ public class LbBuyAccountServiceImpl
|
|||||||
* 单账号抢单逻辑;批量入口为每账号一线程并发调用,共享 {@link LbRushBuyGoodsCoordinator}。
|
* 单账号抢单逻辑;批量入口为每账号一线程并发调用,共享 {@link LbRushBuyGoodsCoordinator}。
|
||||||
*/
|
*/
|
||||||
private Map<String, Object> processSingleAccountRushBuy(
|
private Map<String, Object> processSingleAccountRushBuy(
|
||||||
String id, LbBuyAccount account, LbRushBuyGoodsCoordinator goodsCoordinator) {
|
String id, LbBuyAccount account, LbRushBuyGoodsCoordinator goodsCoordinator, String goodsBeginTime) {
|
||||||
String accountLabel = formatRushBuyAccountLabel(id, account);
|
String accountLabel = formatRushBuyAccountLabel(id, account);
|
||||||
log.info("抢单任务开始,{},thread={}", accountLabel, Thread.currentThread().getName());
|
log.info("抢单任务开始,{},thread={}", accountLabel, Thread.currentThread().getName());
|
||||||
Map<String, Object> item = new LinkedHashMap<>();
|
Map<String, Object> item = new LinkedHashMap<>();
|
||||||
@@ -389,7 +389,8 @@ public class LbBuyAccountServiceImpl
|
|||||||
tokenRefreshContext,
|
tokenRefreshContext,
|
||||||
goodsCoordinator,
|
goodsCoordinator,
|
||||||
account.getId(),
|
account.getId(),
|
||||||
maxGrabAmount);
|
maxGrabAmount,
|
||||||
|
goodsBeginTime);
|
||||||
item.put("rushBuyResult", rushBuyResult);
|
item.put("rushBuyResult", rushBuyResult);
|
||||||
rushSuccess = rushBuyResult.get("success") instanceof Boolean
|
rushSuccess = rushBuyResult.get("success") instanceof Boolean
|
||||||
? (Boolean) rushBuyResult.get("success")
|
? (Boolean) rushBuyResult.get("success")
|
||||||
|
|||||||
@@ -529,7 +529,8 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
|
|||||||
LbBuyAccountRushBuyContext tokenRefreshContext,
|
LbBuyAccountRushBuyContext tokenRefreshContext,
|
||||||
LbRushBuyGoodsCoordinator goodsCoordinator,
|
LbRushBuyGoodsCoordinator goodsCoordinator,
|
||||||
String accountId,
|
String accountId,
|
||||||
Integer maxGrabAmount) {
|
Integer maxGrabAmount,
|
||||||
|
String goodsBeginTime) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
String accountTag = formatRushBuyAccountLogTag(rushBuyAccountLabel);
|
String accountTag = formatRushBuyAccountLogTag(rushBuyAccountLabel);
|
||||||
try {
|
try {
|
||||||
@@ -562,10 +563,13 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
|
|||||||
TenantContextHolder.setTenantId(tid);
|
TenantContextHolder.setTenantId(tid);
|
||||||
try {
|
try {
|
||||||
log.info("查询-待抢购-货物列表......");
|
log.info("查询-待抢购-货物列表......");
|
||||||
List<LbGoods> goodsList = resolveRushBuyGoodsList(tid, accountTag, goodsCoordinator);//
|
List<LbGoods> goodsList = resolveRushBuyGoodsList(tid, accountTag, goodsCoordinator, goodsBeginTime);
|
||||||
if (goodsList.isEmpty()) {
|
if (goodsList.isEmpty()) {
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
result.put("message", "lb_goods 中无可抢购货品(金额需大于25000且不超过38000,且更新时间需在24小时内)");
|
String timeCondition = goodsBeginTime != null && !goodsBeginTime.trim().isEmpty()
|
||||||
|
? "且更新时间需大于 goodsBeginTime(" + goodsBeginTime + ")"
|
||||||
|
: "且更新时间需在24小时内";
|
||||||
|
result.put("message", "lb_goods 中无可抢购货品(金额需大于25000且不超过38000," + timeCondition + ")");
|
||||||
result.put("successCount", 0);
|
result.put("successCount", 0);
|
||||||
result.put("failCount", 0);
|
result.put("failCount", 0);
|
||||||
result.put("details", List.of());
|
result.put("details", List.of());
|
||||||
@@ -849,9 +853,9 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<LbGoods> resolveRushBuyGoodsList(
|
private List<LbGoods> resolveRushBuyGoodsList(
|
||||||
String tid, String accountTag, LbRushBuyGoodsCoordinator goodsCoordinator) {
|
String tid, String accountTag, LbRushBuyGoodsCoordinator goodsCoordinator, String goodsBeginTime) {
|
||||||
if (goodsCoordinator == null) {
|
if (goodsCoordinator == null) {
|
||||||
return loadRushBuyGoodsList(tid, accountTag);
|
return loadRushBuyGoodsList(tid, accountTag, goodsBeginTime);
|
||||||
}
|
}
|
||||||
List<LbGoods> cached = goodsCoordinator.peekRushBuyGoodsList(tid);
|
List<LbGoods> cached = goodsCoordinator.peekRushBuyGoodsList(tid);
|
||||||
if (cached != null) {
|
if (cached != null) {
|
||||||
@@ -863,27 +867,43 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
|
|||||||
}
|
}
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
return goodsCoordinator.resolveRushBuyGoodsList(tid, () -> loadRushBuyGoodsList(tid, accountTag));
|
return goodsCoordinator.resolveRushBuyGoodsList(tid, () -> loadRushBuyGoodsList(tid, accountTag, goodsBeginTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<LbGoods> loadRushBuyGoodsList(String tid, String accountTag) {
|
private List<LbGoods> loadRushBuyGoodsList(String tid, String accountTag, String goodsBeginTime) {
|
||||||
LocalDateTime updatedAfter = resolveRushBuyUpdatedAfter();
|
LocalDateTime updatedAfter;
|
||||||
|
boolean useGoodsBeginTime = goodsBeginTime != null && !goodsBeginTime.trim().isEmpty();
|
||||||
|
if (useGoodsBeginTime) {
|
||||||
|
try {
|
||||||
|
updatedAfter = LocalDateTime.parse(goodsBeginTime.trim(), DATETIME_FMT);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
log.warn("goodsBeginTime 格式错误,忽略该参数,使用默认时间范围,goodsBeginTime={}", goodsBeginTime);
|
||||||
|
updatedAfter = resolveRushBuyUpdatedAfter();
|
||||||
|
useGoodsBeginTime = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updatedAfter = resolveRushBuyUpdatedAfter();
|
||||||
|
}
|
||||||
LambdaQueryWrapper<LbGoods> w = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<LbGoods> w = new LambdaQueryWrapper<>();
|
||||||
w.eq(LbGoods::getTenantId, tid);
|
w.eq(LbGoods::getTenantId, tid);
|
||||||
w.isNotNull(LbGoods::getSellerId);
|
w.isNotNull(LbGoods::getSellerId);
|
||||||
w.gt(LbGoods::getTotalMoney, RUSH_BUY_MIN_TOTAL_MONEY);
|
w.gt(LbGoods::getTotalMoney, RUSH_BUY_MIN_TOTAL_MONEY);
|
||||||
w.le(LbGoods::getTotalMoney, RUSH_BUY_MAX_TOTAL_MONEY);
|
w.le(LbGoods::getTotalMoney, RUSH_BUY_MAX_TOTAL_MONEY);
|
||||||
|
if (useGoodsBeginTime) {
|
||||||
|
w.gt(LbGoods::getUpdatedAt, updatedAfter);
|
||||||
|
} else {
|
||||||
w.ge(LbGoods::getUpdatedAt, updatedAfter);
|
w.ge(LbGoods::getUpdatedAt, updatedAfter);
|
||||||
|
}
|
||||||
w.orderByDesc(LbGoods::getTotalMoney);
|
w.orderByDesc(LbGoods::getTotalMoney);
|
||||||
long goodsQueryStartedAt = System.nanoTime();
|
long goodsQueryStartedAt = System.nanoTime();
|
||||||
List<LbGoods> goodsList = this.list(w);
|
List<LbGoods> goodsList = this.list(w);
|
||||||
long goodsQueryElapsedMs = (System.nanoTime() - goodsQueryStartedAt) / 1_000_000L;
|
long goodsQueryElapsedMs = (System.nanoTime() - goodsQueryStartedAt) / 1_000_000L;
|
||||||
if (accountTag.isEmpty()) {
|
if (accountTag.isEmpty()) {
|
||||||
log.info("rushBuy 查询可抢货品耗时 {} ms,tenantId={},updatedAfter={},结果数量={}",
|
log.info("rushBuy 查询可抢货品耗时 {} ms,tenantId={},updatedAfter={},goodsBeginTime={},结果数量={}",
|
||||||
goodsQueryElapsedMs, tid, updatedAfter, goodsList.size());
|
goodsQueryElapsedMs, tid, updatedAfter, goodsBeginTime, goodsList.size());
|
||||||
} else {
|
} else {
|
||||||
log.info("{} rushBuy 查询可抢货品耗时 {} ms,tenantId={},updatedAfter={},结果数量={}",
|
log.info("{} rushBuy 查询可抢货品耗时 {} ms,tenantId={},updatedAfter={},goodsBeginTime={},结果数量={}",
|
||||||
accountTag, goodsQueryElapsedMs, tid, updatedAfter, goodsList.size());
|
accountTag, goodsQueryElapsedMs, tid, updatedAfter, goodsBeginTime, goodsList.size());
|
||||||
}
|
}
|
||||||
return goodsList;
|
return goodsList;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user