fix: prevent duplicate store submissions by adding SUBMITTING state guard
- Add SUBMITTING to skip guard in executeSubmitAsync to prevent concurrent uploads - Add getSubmittingStores() public method to check SUBMITTING state - Add controller-level check to reject submissions when stores are already uploading - Prevents VIVO/Honor 'app is under review' errors from duplicate uploads Co-Authored-By: Claude <noreply@anthropic.com>
这个提交包含在:
父节点
786051510b
当前提交
a6da4f3560
@ -121,6 +121,17 @@ public class AppStoreController {
|
|||||||
if (scheduledPublishAtText != null && !scheduledPublishAtText.isBlank()) {
|
if (scheduledPublishAtText != null && !scheduledPublishAtText.isBlank()) {
|
||||||
scheduledPublishAt = java.time.LocalDateTime.parse(scheduledPublishAtText);
|
scheduledPublishAt = java.time.LocalDateTime.parse(scheduledPublishAtText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reject if any requested store is already uploading (SUBMITTING state)
|
||||||
|
List<String> submitting = submissionService.getSubmittingStores(versionId);
|
||||||
|
if (!submitting.isEmpty()) {
|
||||||
|
List<String> requested = storeTypes != null ? storeTypes : submitting; // null means all targets
|
||||||
|
List<String> conflict = submitting.stream().filter(requested::contains).toList();
|
||||||
|
if (!conflict.isEmpty()) {
|
||||||
|
throw new IllegalStateException("以下渠道正在上传中,请等待完成后再试: " + String.join(", ", conflict));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AppVersionEntity v = storeService.markSubmitted(versionId,
|
AppVersionEntity v = storeService.markSubmitted(versionId,
|
||||||
storeTypes,
|
storeTypes,
|
||||||
submitMode,
|
submitMode,
|
||||||
|
|||||||
@ -184,7 +184,8 @@ public class StoreSubmissionService {
|
|||||||
try {
|
try {
|
||||||
// Skip stores already in active review to avoid duplicate submissions
|
// Skip stores already in active review to avoid duplicate submissions
|
||||||
String activeState = currentStoreState(v.getStoreReviewStatus(), storeType);
|
String activeState = currentStoreState(v.getStoreReviewStatus(), storeType);
|
||||||
if ("UNDER_REVIEW".equals(activeState) || "APPROVED".equals(activeState)) {
|
if ("UNDER_REVIEW".equals(activeState) || "APPROVED".equals(activeState)
|
||||||
|
|| "SUBMITTING".equals(activeState)) {
|
||||||
skippedCount.incrementAndGet();
|
skippedCount.incrementAndGet();
|
||||||
log.info("Skipping {} for version={} batchId={} — already in state {}",
|
log.info("Skipping {} for version={} batchId={} — already in state {}",
|
||||||
storeType, versionId, batchId, activeState);
|
storeType, versionId, batchId, activeState);
|
||||||
@ -1254,6 +1255,37 @@ public class StoreSubmissionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns store types that are currently in SUBMITTING state for the given version.
|
||||||
|
* Used by the controller to reject duplicate submission requests.
|
||||||
|
*/
|
||||||
|
public List<String> getSubmittingStores(String versionId) {
|
||||||
|
AppVersionEntity v = versionRepo.findById(versionId).orElse(null);
|
||||||
|
if (v == null || v.getStoreReviewStatus() == null || v.getStoreReviewStatus().isBlank()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Map<String, Object> reviewMap = mapper.readValue(v.getStoreReviewStatus(), new TypeReference<>() {});
|
||||||
|
List<String> submitting = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, Object> entry : reviewMap.entrySet()) {
|
||||||
|
String store = entry.getKey();
|
||||||
|
String state = "";
|
||||||
|
if (entry.getValue() instanceof Map<?, ?> m) {
|
||||||
|
Object s = m.get("state");
|
||||||
|
state = s instanceof String str ? str : "";
|
||||||
|
} else if (entry.getValue() instanceof String s) {
|
||||||
|
state = s;
|
||||||
|
}
|
||||||
|
if ("SUBMITTING".equals(state)) {
|
||||||
|
submitting.add(store);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return submitting;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void sweepStuckSubmittingForVersion(String versionId, String matchBatchId, String failReason) {
|
private void sweepStuckSubmittingForVersion(String versionId, String matchBatchId, String failReason) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户