perf(lastleg): batch live appointment work facts and filter candidates
This commit is contained in:
+3
@@ -35,6 +35,9 @@ class AppointmentWorkPersistenceTest {
|
||||
assertEquals("运营甲",store.replay(state.getWorkItemKey(),"same-key").getOperatorName());
|
||||
assertThrows(RuntimeException.class,()->store.history(state,new Actor("2","运营乙",ACTOR.permissions()),"SAVE_FOLLOWUP","其他人重复键","same-key","other",Map.of("version",2)));
|
||||
assertEquals(1,store.history(state.getWorkItemKey()).size());
|
||||
mapper.insertCommitment("FBA_APPOINTMENT:1","{}");mapper.updateCommitment("FBA_APPOINTMENT:1","{}",3);
|
||||
var tokens=new AppointmentWorkCommitmentService(mapper,new ObjectMapper()).impactTokens(List.of("FBA_APPOINTMENT:1","FBA_APPOINTMENT:2"));
|
||||
assertEquals(Map.of("FBA_APPOINTMENT:1","FBA_APPOINTMENT:1:3","FBA_APPOINTMENT:2","FBA_APPOINTMENT:2:0"),tokens);
|
||||
}
|
||||
}
|
||||
@Test void transactionRollbackCannotLeaveHalfGeneratedRoute() throws Exception {
|
||||
|
||||
+54
@@ -12,6 +12,60 @@ import static com.baiyue.lastleg.appointmentwork.AppointmentWorkModels.*;
|
||||
import static com.baiyue.lastleg.appointmentwork.AppointmentWorkFactGateway.*;
|
||||
|
||||
class AppointmentWorkQueryServiceTest {
|
||||
@Test void followTodayPageOneSizeEightDoesNotReadUnrelatedRuntimeFactsOrPaginateBeforeCompletionChecks() {
|
||||
var f=new WorkTestFixture();
|
||||
for(int index=0;index<1000;index++) f.add(f.state("unrelated-"+index,Type.WAREHOUSE_RECEIPT,Flow.TRANSFER,null));
|
||||
var expected=new HashSet<String>();
|
||||
var prior=f.state("due-1",Type.PICKUP,Flow.TRANSFER,null);f.add(prior);expected.add(prior.getWorkItemKey());
|
||||
for(int index=1;index<=10;index++) {
|
||||
var state=f.state("due-"+index,Type.DELIVERY,Flow.TRANSFER,"inbound");state.setFollowupDate(LocalDate.of(2026,10,14));
|
||||
if(index==1) state.setPrerequisites(List.of(prior.getWorkItemKey()));
|
||||
if(index==10) f.facts.put(state.getWorkItemKey(),fact(state,null,null,ExecutionStatus.COMPLETED,new Actual(Instant.parse("2026-10-14T12:00:00Z"),null,"America/Los_Angeles")));
|
||||
f.add(state);expected.add(state.getWorkItemKey());
|
||||
}
|
||||
var future=f.state("future",Type.DELIVERY,Flow.TRANSFER,"inbound");future.setFollowupDate(LocalDate.of(2027,1,1));f.add(future);
|
||||
// Exact parameters from /items?view=FOLLOW_TODAY&page=1&size=8.
|
||||
var page=f.queries.items(View.FOLLOW_TODAY,1,8,null,null,null,null,null,null,ACTOR);
|
||||
assertEquals(9,page.total());assertEquals(8,page.records().size());assertEquals(2,page.pages());
|
||||
assertTrue(page.records().stream().allMatch(i->i.executionStatus()==ExecutionStatus.PENDING));
|
||||
verify(f.gateway).facts(argThat(states->states.stream().map(AppointmentWorkState::getWorkItemKey).collect(java.util.stream.Collectors.toSet()).equals(expected)));
|
||||
}
|
||||
@Test void followTodayPreservesAuthoritativeDateLineZonesAndUndatedPendingHandoffs() {
|
||||
var f=new WorkTestFixture();
|
||||
var tomorrow=LocalDate.of(2026,10,16);
|
||||
var east=f.state("east",Type.DELIVERY,Flow.TRANSFER,"inbound");east.setFollowupDate(tomorrow);f.add(east);
|
||||
var west=f.state("west",Type.DELIVERY,Flow.TRANSFER,"inbound");west.setFollowupDate(tomorrow);f.add(west);
|
||||
// Stored timezone is Los Angeles; the live source is already on the following local day.
|
||||
f.facts.put(east.getWorkItemKey(),fact(east,new Slot(tomorrow,null,null,null,"Pacific/Kiritimati"),null,ExecutionStatus.PENDING,null));
|
||||
var handoff=f.state("return",Type.EMPTY_RETURN,Flow.TRANSFER,null);
|
||||
var owner=new Responsibility(ResponsibilityKind.USER,"1","运营甲");
|
||||
handoff.setReturnHandoff(new ReturnHandoff(1,owner,owner,HandoffStatus.PENDING_ACCEPTANCE,"交接"));f.add(handoff);
|
||||
var query=new AppointmentWorkQueryService(f.store,f.gateway,Clock.fixed(Instant.parse("2026-10-15T12:00:00Z"),ZoneOffset.UTC));
|
||||
var page=query.items(View.FOLLOW_TODAY,1,8,null,null,null,null,null,null,ACTOR);
|
||||
assertEquals(Set.of(east.getWorkItemKey(),handoff.getWorkItemKey()),page.records().stream().map(WorkItem::workItemKey).collect(java.util.stream.Collectors.toSet()));
|
||||
}
|
||||
@Test void calendarLoadsOnlyRequestedTypesButUsesCurrentAuthorityDatesAndStillChecksScope() {
|
||||
var f=new WorkTestFixture();
|
||||
var receipt=f.state("1",Type.WAREHOUSE_RECEIPT,Flow.TRANSFER,null);receipt.setTarget(slot("2025-01-01"));f.add(receipt);
|
||||
var pickup=f.state("1",Type.PICKUP,Flow.TRANSFER,null);f.add(pickup);
|
||||
receipt.setPrerequisites(List.of(pickup.getWorkItemKey()));f.store.save(receipt);
|
||||
f.facts.put(receipt.getWorkItemKey(),fact(receipt,slot("2026-10-16"),null,ExecutionStatus.PENDING,null));
|
||||
assertEquals(1,f.queries.calendar(LocalDate.of(2026,10,1),LocalDate.of(2026,10,31),Flow.TRANSFER,Set.of(Type.WAREHOUSE_RECEIPT),ACTOR).total());
|
||||
verify(f.gateway).facts(argThat(states->states.size()==1 && states.get(0).getWorkItemKey().equals(receipt.getWorkItemKey())));
|
||||
verify(f.gateway).discover(null,1);
|
||||
var reader=new Actor("2","无原业务权限",Set.of(LIST));
|
||||
assertEquals(0,f.queries.calendar(LocalDate.of(2026,10,1),LocalDate.of(2026,10,31),null,Set.of(Type.WAREHOUSE_RECEIPT),reader).total());
|
||||
}
|
||||
@Test void filteredItemsLoadPrerequisiteClosureWithoutIncludingUnrelatedContainers() {
|
||||
var f=new WorkTestFixture();
|
||||
var pickup=f.state("1",Type.PICKUP,Flow.TRANSFER,null);f.add(pickup);
|
||||
var retired=f.state("1",Type.ROUTE,Flow.UNKNOWN,null);retired.setRetired(true);retired.setReplacementKeys(List.of(pickup.getWorkItemKey()));f.add(retired);
|
||||
var receipt=f.state("1",Type.WAREHOUSE_RECEIPT,Flow.TRANSFER,null);receipt.setPrerequisites(List.of(retired.getWorkItemKey()));receipt.setObservedFingerprint("old");f.add(receipt);
|
||||
f.add(f.state("2",Type.DELIVERY,Flow.TRANSFER,"other"));
|
||||
var items=f.queries.items(View.ALL,1,20,null,null,Set.of(Type.WAREHOUSE_RECEIPT),"1",null,null,ACTOR);
|
||||
assertEquals(1,items.total());assertEquals(pickup.getWorkItemKey(),items.records().get(0).nextAction().targetWorkItemKey());
|
||||
verify(f.gateway).facts(argThat(states->states.stream().map(AppointmentWorkState::getWorkItemKey).collect(java.util.stream.Collectors.toSet()).equals(Set.of(pickup.getWorkItemKey(),receipt.getWorkItemKey()))));
|
||||
}
|
||||
@Test void globalSummaryRetainsUnknownRoutesAndReturnAfterDeliveryAcrossCalendarFilters() {
|
||||
var f=new WorkTestFixture(); var route=f.state("1",Type.ROUTE,Flow.UNKNOWN,null); route.setFollowupDate(LocalDate.of(2026,10,14)); f.add(route);
|
||||
var returns=f.state("2",Type.EMPTY_RETURN,Flow.DIRECT,null); returns.setTarget(slot("2026-09-01")); f.add(returns);
|
||||
|
||||
Reference in New Issue
Block a user