fix: replay completed pallet operations
This commit is contained in:
+21
@@ -71,6 +71,9 @@ public class PdaPalletOperationService {
|
||||
|
||||
public PalletOperationResponses.Operation assemble(PdaWarehouseIdentity identity,
|
||||
PalletOperationRequests.Assemble request) {
|
||||
PalletOperationResponses.Operation replay = replayIfPresent(identity, "PALLET_ASSEMBLE",
|
||||
request.idempotencyKey(), request);
|
||||
if (replay != null) return replay;
|
||||
Map<String, PalletPhysicalGateway.PalletReference> pallets = resolvePallets(identity.overseasWarehouseId(),
|
||||
request.target(), request.sources());
|
||||
PalletPhysicalGateway.PalletReference target = pallets.get(code(request.target().palletCode()));
|
||||
@@ -85,6 +88,9 @@ public class PdaPalletOperationService {
|
||||
|
||||
public PalletOperationResponses.Operation disassemble(PdaWarehouseIdentity identity,
|
||||
PalletOperationRequests.Disassemble request) {
|
||||
PalletOperationResponses.Operation replay = replayIfPresent(identity, "PALLET_DISASSEMBLE",
|
||||
request.idempotencyKey(), request);
|
||||
if (replay != null) return replay;
|
||||
LinkedHashMap<String, PalletOperationRequests.PalletExpectation> expectations = new LinkedHashMap<>();
|
||||
expectations.put(code(request.source().palletCode()), request.source());
|
||||
request.targets().forEach(value -> expectations.put(code(value.target().palletCode()), value.target()));
|
||||
@@ -109,6 +115,9 @@ public class PdaPalletOperationService {
|
||||
|
||||
public PalletOperationResponses.Operation swap(PdaWarehouseIdentity identity,
|
||||
PalletOperationRequests.Swap request) {
|
||||
PalletOperationResponses.Operation replay = replayIfPresent(identity, "PALLET_SWAP",
|
||||
request.idempotencyKey(), request);
|
||||
if (replay != null) return replay;
|
||||
Map<String, PalletPhysicalGateway.PalletReference> pallets = resolvePallets(identity.overseasWarehouseId(),
|
||||
request.source(), List.of(request.target()));
|
||||
PalletPhysicalGateway.PalletReference source = pallets.get(code(request.source().palletCode()));
|
||||
@@ -129,6 +138,9 @@ public class PdaPalletOperationService {
|
||||
|
||||
public PalletOperationResponses.Operation unbind(PdaWarehouseIdentity identity,
|
||||
PalletOperationRequests.Unbind request) {
|
||||
PalletOperationResponses.Operation replay = replayIfPresent(identity, "PALLET_UNBIND",
|
||||
request.idempotencyKey(), request);
|
||||
if (replay != null) return replay;
|
||||
Map<String, PalletPhysicalGateway.PalletReference> pallets = resolvePallets(identity.overseasWarehouseId(),
|
||||
List.of(request.source()));
|
||||
PalletPhysicalGateway.PalletReference source = pallets.get(code(request.source().palletCode()));
|
||||
@@ -413,6 +425,15 @@ public class PdaPalletOperationService {
|
||||
return value;
|
||||
}
|
||||
|
||||
private PalletOperationResponses.Operation replayIfPresent(PdaWarehouseIdentity identity, String type,
|
||||
String key, Object request) {
|
||||
String normalizedKey = required(key, "幂等键不能为空");
|
||||
PdaPalletOperation existing = mapper.findOperation(identity.operatorKey(), normalizedKey);
|
||||
if (existing == null) return null;
|
||||
validateExisting(existing, type, hash(request));
|
||||
return read(existing).asReplay();
|
||||
}
|
||||
|
||||
private void saveTransitions(long operationId, List<PalletPhysicalGateway.Transition> transitions) {
|
||||
newTransaction.executeWithoutResult(status -> {
|
||||
PdaPalletOperation operation = mapper.selectById(operationId);
|
||||
|
||||
+20
@@ -27,6 +27,7 @@ import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.List;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
@@ -119,6 +120,25 @@ class PdaPalletOperationServiceTest {
|
||||
assertEquals("PDAOPS-LONG-LOCATION-CODE", ledger.getValue().getWarehouseLocationCode());
|
||||
}
|
||||
|
||||
@Test void exactReplayReturnsStoredResultBeforeValidatingChangedPalletVersions() throws Exception {
|
||||
var request = new PalletOperationRequests.Swap("idem-replay",
|
||||
new PalletOperationRequests.PalletExpectation("SOURCE", 1),
|
||||
new PalletOperationRequests.PalletExpectation("TARGET", 2), "swap");
|
||||
PdaPalletOperation existing = new PdaPalletOperation(); existing.setId(500L);
|
||||
existing.setOperationType("PALLET_SWAP"); existing.setStatus("COMPLETED");
|
||||
existing.setRequestHash(ReflectionTestUtils.invokeMethod(service, "hash", request));
|
||||
var stored = new com.baiyue.lastleg.palletops.dto.PalletOperationResponses.Operation(
|
||||
500L, "PALLET_SWAP", "idem-replay", "COMPLETED", false, LocalDateTime.now(), List.of());
|
||||
existing.setResultJson(new ObjectMapper().findAndRegisterModules().writeValueAsString(stored));
|
||||
when(mapper.findOperation("7", "idem-replay")).thenReturn(existing);
|
||||
|
||||
var replay = service.swap(identity(), request);
|
||||
|
||||
assertTrue(replay.replayed());
|
||||
assertEquals(500L, replay.operationId());
|
||||
verifyNoInteractions(physical);
|
||||
}
|
||||
|
||||
private static PdaWarehouseIdentity identity() { return new PdaWarehouseIdentity("7", "picker", 88L); }
|
||||
private static PalletPhysicalGateway.PalletReference pallet(long id, String code, long warehouse, int version) {
|
||||
return new PalletPhysicalGateway.PalletReference(id, code, warehouse, 1000L + id,
|
||||
|
||||
Reference in New Issue
Block a user