package jnpf.dmsService.expiry;
|
|
import jnpf.dmsEntity.storage.expiry.*;
|
import jnpf.dmsMapper.*;
|
import jnpf.dmsService.DmsFileLifecycleService;
|
import jnpf.dmsService.DmsFileValidityProjection;
|
import jnpf.dmsService.search.DmsSearchProperties;
|
import jnpf.dmsService.search.meili.DmsMeilisearchClient;
|
import jnpf.exception.DataException;
|
import org.junit.jupiter.api.Test;
|
import org.mockito.InOrder;
|
import java.util.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.Mockito.*;
|
|
class DmsFileExpiryTest {
|
private final DmsFileExpiryMapper mapper = mock(DmsFileExpiryMapper.class);
|
private final DmsFileExpiryProjectionMapper resources = mock(DmsFileExpiryProjectionMapper.class);
|
private final DmsFileExpiryProjection projection = new DmsFileExpiryProjection(resources, mapper);
|
private final UUID version = UUID.randomUUID();
|
private final Date end = new Date(1700000000000L);
|
|
@Test void expiresBusinessVersionResourceAndRelationsButRetainsPointer() {
|
DmsFileExpiryResource resource = resource("effective", null);
|
when(resources.lockResources("t", version)).thenReturn(List.of(resource));
|
when(resources.disable("t", resource, end, "actor")).thenReturn(1);
|
when(resources.expireBusinessVersion("t", resource, "actor")).thenReturn(1);
|
projection.apply("t", version, end, "actor");
|
InOrder ordered = inOrder(resources, mapper);
|
ordered.verify(resources).hasPendingProjection("t", version);
|
ordered.verify(resources).lockResources("t", version);
|
ordered.verify(resources).disable("t", resource, end, "actor");
|
ordered.verify(resources).expireBusinessVersion("t", resource, "actor");
|
ordered.verify(resources).closeRelations("t", "file", end, "actor");
|
ordered.verify(mapper).enqueueCleanup("t", version);
|
assertEquals("business-version", resource.getCurrentVersionId());
|
}
|
|
@Test void repairsExpiredProjectionAndEnqueuesCenterOnlyVersions() {
|
when(resources.lockResources("t", version)).thenReturn(List.of());
|
projection.apply("t", version, end, "actor");
|
verify(mapper).enqueueCleanup("t", version);
|
verify(resources, never()).disable(any(), any(), any(), any());
|
}
|
|
@Test void refusesToOverwriteOtherDisableReasonsOrAmbiguousMappings() {
|
when(resources.lockResources("t", version)).thenReturn(List.of(resource("disabled", "yichexiao")));
|
assertThrows(DataException.class, () -> projection.apply("t", version, end, "actor"));
|
when(resources.lockResources("t", version)).thenReturn(List.of(resource("effective", null), resource("effective", null)));
|
assertThrows(DataException.class, () -> projection.apply("t", version, end, "actor"));
|
verifyNoInteractions(mapper);
|
}
|
|
@Test void defersExpiryUntilApprovedBusinessProjectionFinishes() {
|
when(resources.hasPendingProjection("t", version)).thenReturn(true);
|
assertThrows(DataException.class, () -> projection.apply("t", version, end, "actor"));
|
verify(resources, never()).lockResources(any(), any());
|
verifyNoInteractions(mapper);
|
}
|
|
@Test void validityProjectionRejectsDisabledBusinessResources() {
|
when(resources.lockResources("t", version)).thenReturn(List.of(resource("disabled", "yidaoqi")));
|
assertThrows(DataException.class, () -> new DmsFileValidityProjection(resources).apply("t", version, end, "actor"));
|
verify(resources, never()).extendValidity(any(), any(), any(), any());
|
}
|
|
@Test void executorSkipsLockedDocumentsAndCandidatesExtendedAfterDiscovery() {
|
DmsFileLifecycleService lifecycle = mock(DmsFileLifecycleService.class);
|
DmsFileExpiryExecutor executor = new DmsFileExpiryExecutor(mapper, lifecycle, new jnpf.dmsService.DmsBusinessLifecycleGuard(null, false));
|
DmsFileExpiryItem item = item();
|
assertFalse(executor.process(item));
|
when(mapper.tryLockDocument("t", item.getDocumentId())).thenReturn(item.getDocumentId());
|
assertFalse(executor.process(item));
|
verifyNoInteractions(lifecycle);
|
when(mapper.dueState("t", version)).thenReturn(item);
|
assertTrue(executor.process(item));
|
verify(lifecycle).updateExpired(argThat(form -> version.equals(form.getFileVersionId())), eq("dms-expiry-job"));
|
}
|
|
@Test void occupiedFileSkipsBeforeDocumentLockAndDoesNotReportApplied() {
|
DmsFileLifecycleService lifecycle = mock(DmsFileLifecycleService.class);
|
jnpf.dmsService.DmsBusinessLifecycleGuard guard = mock(jnpf.dmsService.DmsBusinessLifecycleGuard.class);
|
DmsFileExpiryExecutor executor = new DmsFileExpiryExecutor(mapper, lifecycle, guard);
|
assertFalse(executor.process(item()));
|
verifyNoInteractions(mapper, lifecycle);
|
}
|
|
@Test void defaultJobProcessesDueVersionsAndContinuesAfterFailure() {
|
DmsFileExpiryProperties properties = new DmsFileExpiryProperties();
|
properties.setBatchSize(1);
|
DmsFileExpiryExecutor executor = mock(DmsFileExpiryExecutor.class);
|
DmsFileExpirySearchCleanup cleanup = mock(DmsFileExpirySearchCleanup.class);
|
DmsFileExpiryItem first = item(), second = item(); second.setFileVersionId(UUID.randomUUID());
|
when(mapper.candidates(null, 1)).thenReturn(List.of(first));
|
when(mapper.candidates(first, 1)).thenReturn(List.of(second));
|
when(mapper.candidates(second, 1)).thenReturn(List.of());
|
when(executor.process(first)).thenThrow(new DataException("conflict"));
|
when(executor.process(second)).thenReturn(true);
|
DmsFileExpiryJob job = new DmsFileExpiryJob(properties, mapper, executor, cleanup, new DmsSearchProperties());
|
DmsFileExpiryJob.Result result = job.run();
|
assertEquals(2, result.getScanned()); assertEquals(1, result.getFailed()); assertEquals(1, result.getApplied());
|
verify(executor).process(first);
|
verify(executor).process(second);
|
verifyNoInteractions(cleanup);
|
}
|
|
@Test void sharedCleanupRunsEvenWhenNoVersionsAreDue() {
|
when(mapper.candidates(null, 100)).thenReturn(List.of());
|
DmsFileExpiryItem receipt = item();
|
when(mapper.cleanupCandidates(100)).thenReturn(List.of(receipt));
|
DmsFileExpiryExecutor executor = mock(DmsFileExpiryExecutor.class);
|
DmsFileExpirySearchCleanup cleanup = mock(DmsFileExpirySearchCleanup.class);
|
DmsSearchProperties search = new DmsSearchProperties(); search.setEnabled(true);
|
DmsFileExpiryJob.Result result = new DmsFileExpiryJob(new DmsFileExpiryProperties(), mapper, executor, cleanup, search).run();
|
assertEquals(0, result.getScanned());
|
verify(cleanup).process(receipt);
|
verifyNoInteractions(executor);
|
}
|
|
@Test void cleanupPersistsAcceptedTaskAndWaitsForConfirmedSuccess() throws Exception {
|
DmsMeilisearchClient client = mock(DmsMeilisearchClient.class);
|
DmsFileExpirySearchCleanup worker = new DmsFileExpirySearchCleanup(mapper, client, new DmsFileExpiryProperties());
|
DmsFileExpiryItem item = item();
|
when(mapper.lockCleanup("t", version)).thenReturn(item);
|
when(client.deleteDocument("t", version)).thenReturn(42L);
|
worker.process(item);
|
verify(mapper).updateCleanup(item, false, null, 60);
|
when(client.taskStatus(42L)).thenReturn("succeeded");
|
worker.process(item);
|
verify(mapper).updateCleanup(item, true, null, 60);
|
verify(client, times(1)).deleteDocument("t", version);
|
}
|
|
@Test void cleanupRetriesFailedOrLostTasksAndRetainsNetworkFailures() throws Exception {
|
DmsMeilisearchClient client = mock(DmsMeilisearchClient.class);
|
DmsFileExpirySearchCleanup worker = new DmsFileExpirySearchCleanup(mapper, client, new DmsFileExpiryProperties());
|
DmsFileExpiryItem item = item(); item.setSearchTaskId(42L);
|
when(mapper.lockCleanup("t", version)).thenReturn(item);
|
when(client.taskStatus(42L)).thenReturn("failed");
|
worker.process(item);
|
assertNull(item.getSearchTaskId());
|
when(client.deleteDocument("t", version)).thenThrow(new java.io.IOException("offline"));
|
worker.process(item);
|
verify(mapper).updateCleanup(item, false, "IOException: offline", 60);
|
}
|
|
private DmsFileExpiryResource resource(String status, String reason) {
|
DmsFileExpiryResource value = new DmsFileExpiryResource();
|
value.setId("file"); value.setCurrentVersionId("business-version"); value.setCenterVersionId(version.toString());
|
value.setVersionCenterId(version.toString()); value.setBizStatus(status); value.setDisabledSource(reason);
|
return value;
|
}
|
private DmsFileExpiryItem item() {
|
DmsFileExpiryItem value = new DmsFileExpiryItem();
|
value.setTenantId("t"); value.setDocumentId(UUID.randomUUID()); value.setFileVersionId(version);
|
value.setLifecycleStatus("EFFECTIVE"); value.setEffectiveFrom(new Date(1600000000000L)); value.setEffectiveTo(end);
|
return value;
|
}
|
}
|