fix(lastleg): read committed order command replays after lock waits
This commit is contained in:
+26
@@ -137,6 +137,32 @@ class InventoryHoldConcurrencyPersistenceTest {
|
||||
assertEquals(12,amount("available_packages")+amount("hold_packages")+amount("allocated_packages")+amount("picked_packages")+shipped);
|
||||
assertEquals(shipped,jdbc.queryForObject("SELECT COALESCE(-SUM(delta_packages),0) FROM ll_inventory_ledger WHERE business_type='SHIP'",Long.class));
|
||||
}
|
||||
@Test void simultaneousDuplicateHoldAndReleaseAdvanceOnceAndKeepIndependentHold() throws Exception {
|
||||
inventory.hold("C1","operator",move(22,2,"OTHER-HOLD"));
|
||||
ExecutorService pool=Executors.newFixedThreadPool(2);
|
||||
try {
|
||||
for (boolean held : new boolean[]{true,false}) {
|
||||
int version=held?0:1;
|
||||
String key=held?"parallel-hold":"parallel-release";
|
||||
var ready=new CountDownLatch(2);var start=new CountDownLatch(1);
|
||||
Callable<LastlegOrderCommandDtos.HoldResponse> command=()->{
|
||||
ready.countDown();await(start);
|
||||
return orders.hold("C1",11,key,new LastlegOrderCommandDtos.HoldRequest(held,false,"quality",version),"operator","Operator");
|
||||
};
|
||||
var first=pool.submit(command);var second=pool.submit(command);
|
||||
await(ready);start.countDown();
|
||||
var response=first.get(8,TimeUnit.SECONDS);
|
||||
assertEquals(response,second.get(8,TimeUnit.SECONDS));
|
||||
assertEquals(version+1,response.version());
|
||||
assertEquals(version+1,orderMapper.selectById(11L).getVersion());
|
||||
}
|
||||
assertEquals(2,count("ll_order_command_record"));
|
||||
assertEquals(2,count("ll_order_hold_history"));
|
||||
assertEquals(5,count("ll_inventory_operation"));
|
||||
assertEquals(5,count("ll_inventory_ledger"));
|
||||
assertEquals(10,amount("available_packages"));assertEquals(2,amount("hold_packages"));conserved(0);
|
||||
} finally {pool.shutdownNow();assertTrue(pool.awaitTermination(10,TimeUnit.SECONDS));}
|
||||
}
|
||||
@Test void secondHoldCycleMustMoveInventoryAgainAndNotReuseTheFirstCycle() {
|
||||
hold(true,0,"hold-one"); hold(false,1,"release-one"); hold(true,2,"hold-two");
|
||||
assertEquals(0,amount("available_packages")); assertEquals(12,amount("hold_packages"));
|
||||
|
||||
+12
@@ -66,6 +66,18 @@ class LastlegOrderCommandServiceTest {
|
||||
ReflectionTestUtils.setField(service, "objectMapper", JsonMapper.builder().findAndAddModules().build());
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandTransactionsReadCommittedAfterWaitingForTheOrderLock() throws Exception {
|
||||
for (var entry : List.of(
|
||||
new Object[]{"hold", LastlegOrderCommandDtos.HoldRequest.class},
|
||||
new Object[]{"saveManualNodes", LastlegOrderCommandDtos.ManualNodesRequest.class})) {
|
||||
var method=LastlegOrderCommandService.class.getMethod((String)entry[0],String.class,long.class,
|
||||
String.class,(Class<?>)entry[1],String.class,String.class);
|
||||
assertEquals(org.springframework.transaction.annotation.Isolation.READ_COMMITTED,
|
||||
method.getAnnotation(org.springframework.transaction.annotation.Transactional.class).isolation());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void holdsOnlySelectedOrderWithVersionAndImmutableHistory() {
|
||||
LastlegOrder order = order(11L, 3);
|
||||
|
||||
Reference in New Issue
Block a user