优化
This commit is contained in:
@@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/** Firstleg internal contract for provisioning one customer dimension rule. */
|
||||
/** Firstleg internal contract for atomically provisioning four default box-size dimension records. */
|
||||
@FeignClient(name = "firstleg-service", contextId = "customerDimensionRuleClient",
|
||||
url = "${baiyue.clients.firstleg.url:}",
|
||||
path = "/internal/firstleg/v1/customer-dimension-configs")
|
||||
@@ -25,5 +25,6 @@ public interface CustomerDimensionRuleClient {
|
||||
@RequestParam String initializationKey);
|
||||
|
||||
record InitializationRequest(long tenantId, long operatorId, String initializationKey) { }
|
||||
/** configId is the first record ID retained only for contract compatibility. */
|
||||
record InitializationResponse(Long configId, boolean createdByThisInitialization) { }
|
||||
}
|
||||
|
||||
+8
-8
@@ -12,7 +12,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/** Provisions the customer dimension rule and compensates it when local customer creation rolls back. */
|
||||
/** Provisions four default box-size dimensions and compensates them when customer creation rolls back. */
|
||||
@Service
|
||||
public class CustomerDimensionRuleInitializationService {
|
||||
private static final Logger log = LoggerFactory.getLogger(CustomerDimensionRuleInitializationService.class);
|
||||
@@ -40,13 +40,13 @@ public class CustomerDimensionRuleInitializationService {
|
||||
return result;
|
||||
}
|
||||
lastFailure = unavailable(response);
|
||||
log.warn("客户尺寸规则初始化失败,tenantId={}, attempt={}, code={}, requestId={}, traceId={}",
|
||||
log.warn("客户4条默认箱规尺寸初始化失败,tenantId={}, attempt={}, code={}, requestId={}, traceId={}",
|
||||
tenantId, attempt, response == null ? null : response.code(),
|
||||
response == null ? null : response.requestId(),
|
||||
response == null ? null : response.traceId());
|
||||
} catch (RuntimeException failure) {
|
||||
lastFailure = failure;
|
||||
log.warn("客户尺寸规则初始化调用异常,tenantId={}, attempt={}", tenantId, attempt, failure);
|
||||
log.warn("客户4条默认箱规尺寸初始化调用异常,tenantId={}, attempt={}", tenantId, attempt, failure);
|
||||
}
|
||||
}
|
||||
compensateAfterUncertainInitialization(tenantId, initializationKey);
|
||||
@@ -67,7 +67,7 @@ public class CustomerDimensionRuleInitializationService {
|
||||
try {
|
||||
compensateRequired(tenantId, result.initializationKey());
|
||||
} catch (RuntimeException compensationFailure) {
|
||||
log.error("客户创建事务回滚后尺寸规则补偿失败,tenantId={}, initializationKey={}",
|
||||
log.error("客户创建事务回滚后4条默认箱规尺寸补偿失败,tenantId={}, initializationKey={}",
|
||||
tenantId, result.initializationKey(), compensationFailure);
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class CustomerDimensionRuleInitializationService {
|
||||
try {
|
||||
compensateRequired(tenantId, initializationKey);
|
||||
} catch (RuntimeException compensationFailure) {
|
||||
log.error("客户尺寸规则初始化结果不确定且补偿失败,tenantId={}, initializationKey={}",
|
||||
log.error("客户4条默认箱规尺寸初始化结果不确定且补偿失败,tenantId={}, initializationKey={}",
|
||||
tenantId, initializationKey, compensationFailure);
|
||||
}
|
||||
}
|
||||
@@ -95,20 +95,20 @@ public class CustomerDimensionRuleInitializationService {
|
||||
}
|
||||
}
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE,
|
||||
"客户尺寸规则补偿失败,请根据客户ID修复数据一致性: " + tenantId);
|
||||
"客户4条默认箱规尺寸补偿失败,请根据客户ID修复数据一致性: " + tenantId);
|
||||
}
|
||||
|
||||
private static BizException unavailable(ApiResponse<?> response) {
|
||||
String detail = response == null || response.message() == null || response.message().isBlank()
|
||||
? "Firstleg 服务未返回有效响应" : response.message();
|
||||
return new BizException(ResultCode.SERVICE_UNAVAILABLE, "默认尺寸规则初始化失败: " + detail);
|
||||
return new BizException(ResultCode.SERVICE_UNAVAILABLE, "4条默认箱规尺寸初始化失败: " + detail);
|
||||
}
|
||||
|
||||
private static BizException unavailable(RuntimeException cause) {
|
||||
String detail = cause == null || cause.getMessage() == null || cause.getMessage().isBlank()
|
||||
? "Firstleg 服务暂时不可用" : cause.getMessage();
|
||||
return new BizException(ResultCode.SERVICE_UNAVAILABLE,
|
||||
"默认尺寸规则初始化失败,已重试 3 次: " + detail);
|
||||
"4条默认箱规尺寸初始化失败,已重试 3 次: " + detail);
|
||||
}
|
||||
|
||||
private static String initializationKey(long tenantId) {
|
||||
|
||||
+4
-1
@@ -9,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CustomerDimensionRuleClientContractTest {
|
||||
@Test
|
||||
void usesTheFirstlegInternalDimensionConfigContract() throws Exception {
|
||||
void usesOneAtomicCallForTheFourDefaultBoxDimensionRecords() throws Exception {
|
||||
FeignClient feign = CustomerDimensionRuleClient.class.getAnnotation(FeignClient.class);
|
||||
PostMapping initialize = CustomerDimensionRuleClient.class
|
||||
.getMethod("initialize", String.class,
|
||||
@@ -23,5 +23,8 @@ class CustomerDimensionRuleClientContractTest {
|
||||
assertThat(feign.path()).isEqualTo("/internal/firstleg/v1/customer-dimension-configs");
|
||||
assertThat(initialize.value()).containsExactly("/defaults");
|
||||
assertThat(compensate.value()).containsExactly("/defaults");
|
||||
assertThat(CustomerDimensionRuleClient.InitializationResponse.class.getRecordComponents())
|
||||
.extracting(java.lang.reflect.RecordComponent::getName)
|
||||
.containsExactly("configId", "createdByThisInitialization");
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -42,7 +42,7 @@ class CustomerDimensionRuleInitializationServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void retriesWithOneStableKeyAndReturnsTheIdempotentResult() {
|
||||
void retriesOneAtomicFourBoxDefaultsCallWithAStableKey() {
|
||||
when(client.initialize(anyString(), any()))
|
||||
.thenThrow(new RuntimeException("timeout"))
|
||||
.thenReturn(ApiResponse.failure(ResultCode.SERVICE_UNAVAILABLE,
|
||||
@@ -66,7 +66,7 @@ class CustomerDimensionRuleInitializationServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void reportsServiceUnavailableAfterThreeFailedAttemptsAndTriesCompensation() {
|
||||
void reportsServiceUnavailableWhenFourBoxDefaultsFailThreeTimesAndTriesCompensation() {
|
||||
when(client.initialize(anyString(), any())).thenThrow(new RuntimeException("timeout"));
|
||||
when(client.compensate(anyString(), anyLong(), anyString())).thenReturn(ApiResponse.success(null));
|
||||
|
||||
@@ -78,7 +78,7 @@ class CustomerDimensionRuleInitializationServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void localRollbackCompensatesOnlyAConfigurationCreatedByThisRegistration() {
|
||||
void localRollbackCompensatesFourBoxDefaultsCreatedByThisRegistration() {
|
||||
when(client.initialize(anyString(), any()))
|
||||
.thenReturn(ApiResponse.success(new CustomerDimensionRuleClient.InitializationResponse(91L, true)));
|
||||
when(client.compensate(anyString(), anyLong(), anyString())).thenReturn(ApiResponse.success(null));
|
||||
@@ -95,7 +95,7 @@ class CustomerDimensionRuleInitializationServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void localRollbackDoesNotDeleteAConfigurationThatAlreadyExisted() {
|
||||
void localRollbackKeepsFourBoxDefaultsThatAlreadyExisted() {
|
||||
when(client.initialize(anyString(), any()))
|
||||
.thenReturn(ApiResponse.success(new CustomerDimensionRuleClient.InitializationResponse(91L, false)));
|
||||
TransactionSynchronizationManager.initSynchronization();
|
||||
@@ -110,7 +110,7 @@ class CustomerDimensionRuleInitializationServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void responseTimeoutThenIdempotentSuccessStillCompensatesOnLocalRollback() {
|
||||
void responseTimeoutThenIdempotentFourBoxSuccessStillCompensatesOnLocalRollback() {
|
||||
when(client.initialize(anyString(), any()))
|
||||
.thenThrow(new RuntimeException("response timeout"))
|
||||
.thenReturn(ApiResponse.success(new CustomerDimensionRuleClient.InitializationResponse(91L, true)));
|
||||
|
||||
@@ -115,7 +115,7 @@ class MerchantOnboardingServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void clientRegistrationFailsWhenDefaultDimensionRuleCannotBeInitialized() {
|
||||
void clientRegistrationFailsWhenFourDefaultBoxDimensionsCannotBeInitialized() {
|
||||
IamRole ownerRole = new IamRole();
|
||||
ownerRole.setId(4000100L);
|
||||
ownerRole.setTenantId(0L);
|
||||
|
||||
@@ -183,7 +183,7 @@ class TenantServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void platformRegistrationFailsWhenDefaultDimensionRuleCannotBeInitialized() {
|
||||
void platformRegistrationFailsWhenFourDefaultBoxDimensionsCannotBeInitialized() {
|
||||
doThrow(new BizException(ResultCode.SERVICE_UNAVAILABLE, "初始化失败"))
|
||||
.when(dimensionRuleInitialization).initialize(any(Long.class), any(Long.class));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user