fix(appointment): keep source inspection in work transaction
This commit is contained in:
+4
@@ -40,6 +40,10 @@ public class AppointmentCargoVerificationService {
|
|||||||
|
|
||||||
@Transactional(readOnly=true)
|
@Transactional(readOnly=true)
|
||||||
public Context get(String sourceKey,String customerId,String destinationKey) {
|
public Context get(String sourceKey,String customerId,String destinationKey) {
|
||||||
|
return inspect(sourceKey,customerId,destinationKey);
|
||||||
|
}
|
||||||
|
/** Caller-owned transaction: a handled read prerequisite must not mark the whole work scan rollback-only. */
|
||||||
|
public Context inspect(String sourceKey,String customerId,String destinationKey) {
|
||||||
var source=sources.resolve(sourceKey,customerId,destinationKey);
|
var source=sources.resolve(sourceKey,customerId,destinationKey);
|
||||||
return inspect(source);
|
return inspect(source);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ public class AppointmentWorkDeliveryProvider implements AppointmentWorkFactGatew
|
|||||||
else {
|
else {
|
||||||
for(var source:request.sources()) {
|
for(var source:request.sources()) {
|
||||||
try {
|
try {
|
||||||
var context=cargo.get(source.sourceKey(),source.customerId(),source.destinationKey());
|
var context=cargo.inspect(source.sourceKey(),source.customerId(),source.destinationKey());
|
||||||
fingerprints.add(context.toString()); blocks.addAll(context.blockReasons());
|
fingerprints.add(context.toString()); blocks.addAll(context.blockReasons());
|
||||||
} catch(org.springframework.web.server.ResponseStatusException error) {
|
} catch(org.springframework.web.server.ResponseStatusException error) {
|
||||||
if(!AppointmentWorkSourceAvailability.unresolved(error)) throw error;
|
if(!AppointmentWorkSourceAvailability.unresolved(error)) throw error;
|
||||||
|
|||||||
+19
-2
@@ -12,15 +12,32 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
class AppointmentWorkDeliveryProviderTest {
|
class AppointmentWorkDeliveryProviderTest {
|
||||||
|
@Test void handledPrerequisiteCommitsTheCallerTransactionThroughTheRealCargoProxy() {
|
||||||
|
var sourceService=mock(com.baiyue.lastleg.appointmentplanning.AppointmentSourceService.class);
|
||||||
|
when(sourceService.resolve("ORDER:11","C",null)).thenThrow(new org.springframework.web.server.ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST,"当前货源类型不支持FBA预约"));
|
||||||
|
var cargo=new AppointmentCargoVerificationService(sourceService,mock(com.baiyue.lastleg.appointmentplanning.AppointmentCargoVerificationMapper.class),new com.fasterxml.jackson.databind.ObjectMapper());
|
||||||
|
var ds=new org.h2.jdbcx.JdbcDataSource();ds.setURL("jdbc:h2:mem:work-read-tx-"+java.util.UUID.randomUUID()+";DB_CLOSE_DELAY=-1");
|
||||||
|
var manager=new org.springframework.jdbc.datasource.DataSourceTransactionManager(ds);
|
||||||
|
var proxy=new org.springframework.aop.framework.ProxyFactory(cargo);proxy.setProxyTargetClass(true);
|
||||||
|
proxy.addAdvice(new org.springframework.transaction.interceptor.TransactionInterceptor(manager,new org.springframework.transaction.annotation.AnnotationTransactionAttributeSource()));
|
||||||
|
var provider=new AppointmentWorkDeliveryProvider(mock(InboundFbaAppointmentService.class),(AppointmentCargoVerificationService)proxy.getProxy(),mock(AppointmentWorkCommitmentService.class),mock(AppointmentWorkDeliveryMapper.class),mock(AppointmentWorkSourceMapper.class));
|
||||||
|
var jdbc=new org.springframework.jdbc.core.JdbcTemplate(ds);jdbc.execute("CREATE TABLE work_probe(id INT PRIMARY KEY)");
|
||||||
|
var request=new FactRequest("W",Type.DELIVERY,Flow.TRANSFER,"1","INBOUND:1",null,null,List.of(),List.of(),List.of(new SourceReference("C","ORDER:11",null)));
|
||||||
|
new org.springframework.transaction.support.TransactionTemplate(manager).executeWithoutResult(tx->{
|
||||||
|
var fact=provider.read(List.of(request)).get(0);assertNull(fact.action());assertEquals(List.of("SOURCE_CONFIGURATION"),fact.missingFields());
|
||||||
|
jdbc.update("INSERT INTO work_probe VALUES (1)");
|
||||||
|
});
|
||||||
|
assertEquals(1,jdbc.queryForObject("SELECT COUNT(*) FROM work_probe",Integer.class));
|
||||||
|
}
|
||||||
@Test void knownSourcePrerequisiteIsVisibleAndCannotOfferBookingButOutagesStillFail() {
|
@Test void knownSourcePrerequisiteIsVisibleAndCannotOfferBookingButOutagesStillFail() {
|
||||||
var cargo=mock(AppointmentCargoVerificationService.class);var sources=mock(AppointmentWorkSourceMapper.class);
|
var cargo=mock(AppointmentCargoVerificationService.class);var sources=mock(AppointmentWorkSourceMapper.class);
|
||||||
var provider=new AppointmentWorkDeliveryProvider(mock(InboundFbaAppointmentService.class),cargo,mock(AppointmentWorkCommitmentService.class),mock(AppointmentWorkDeliveryMapper.class),sources);
|
var provider=new AppointmentWorkDeliveryProvider(mock(InboundFbaAppointmentService.class),cargo,mock(AppointmentWorkCommitmentService.class),mock(AppointmentWorkDeliveryMapper.class),sources);
|
||||||
var request=new FactRequest("W",Type.DELIVERY,Flow.TRANSFER,"1","INBOUND:1",null,null,List.of(),List.of(),List.of(new SourceReference("C","ORDER:11",null)));
|
var request=new FactRequest("W",Type.DELIVERY,Flow.TRANSFER,"1","INBOUND:1",null,null,List.of(),List.of(),List.of(new SourceReference("C","ORDER:11",null)));
|
||||||
when(cargo.get("ORDER:11","C",null)).thenThrow(new org.springframework.web.server.ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST,"接仓点不在启用的美国仓目录中"));
|
when(cargo.inspect("ORDER:11","C",null)).thenThrow(new org.springframework.web.server.ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST,"接仓点不在启用的美国仓目录中"));
|
||||||
var fact=provider.read(List.of(request)).get(0);
|
var fact=provider.read(List.of(request)).get(0);
|
||||||
assertEquals(ExecutionStatus.PENDING,fact.executionStatus());assertNull(fact.action());assertNull(fact.actual());
|
assertEquals(ExecutionStatus.PENDING,fact.executionStatus());assertNull(fact.action());assertNull(fact.actual());
|
||||||
assertEquals(List.of("SOURCE_CONFIGURATION"),fact.missingFields());assertEquals(List.of("接仓点不在启用的美国仓目录中"),fact.blockReasons());
|
assertEquals(List.of("SOURCE_CONFIGURATION"),fact.missingFields());assertEquals(List.of("接仓点不在启用的美国仓目录中"),fact.blockReasons());
|
||||||
doThrow(new org.springframework.web.server.ResponseStatusException(org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE,"服务不可用")).when(cargo).get("ORDER:11","C",null);
|
doThrow(new org.springframework.web.server.ResponseStatusException(org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE,"服务不可用")).when(cargo).inspect("ORDER:11","C",null);
|
||||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,()->provider.read(List.of(request)));
|
assertThrows(org.springframework.web.server.ResponseStatusException.class,()->provider.read(List.of(request)));
|
||||||
}
|
}
|
||||||
@Test void privateCompletionCoversThisDispatchPerSourceWithoutCompletingTheWholeOrder() {
|
@Test void privateCompletionCoversThisDispatchPerSourceWithoutCompletingTheWholeOrder() {
|
||||||
|
|||||||
Reference in New Issue
Block a user