package jnpf.dmsService.pdf;
|
|
import jnpf.base.ActionResult;
|
import jnpf.dms.DmsPersistentPdfApi;
|
import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
|
import jnpf.dmsEntity.storage.entity.DmsFileObjectEntity;
|
import jnpf.dmsEntity.storage.pdf.DmsPdfGenerationTask;
|
import jnpf.dmsEntity.storage.vo.DmsPersistentPdfGenerateVO;
|
import jnpf.dmsMapper.DmsFileObjectMapper;
|
import jnpf.dmsMapper.DmsFileVersionMapper;
|
import jnpf.dmsMapper.DmsPdfGenerationTaskMapper;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
|
import java.lang.reflect.Field;
|
import java.util.UUID;
|
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
class DmsPdfGenerationJobTest {
|
private static final String TENANT = "tenant-1";
|
private static final UUID VERSION_ID =
|
UUID.fromString("018f0000-0000-7000-8000-000000000702");
|
private static final String CHECKSUM = "a".repeat(64);
|
|
private final DmsPdfGenerationTaskMapper tasks = mock(DmsPdfGenerationTaskMapper.class);
|
private final DmsFileVersionMapper versions = mock(DmsFileVersionMapper.class);
|
private final DmsFileObjectMapper objects = mock(DmsFileObjectMapper.class);
|
private final DmsPersistentPdfApi fileApi = mock(DmsPersistentPdfApi.class);
|
private final DmsPdfGenerationCompletion completion = mock(DmsPdfGenerationCompletion.class);
|
private final DmsPdfGenerationJob job =
|
new DmsPdfGenerationJob(tasks, versions, objects, fileApi, completion);
|
|
@BeforeEach
|
void configure() throws Exception {
|
set("maxAttempts", 8);
|
set("leaseSeconds", 300);
|
}
|
|
@Test
|
void skipsTaskWhenAnotherWorkerOwnsTheLease() {
|
DmsPdfGenerationTask task = task(0);
|
when(tasks.claim(eq(TENANT), eq(VERSION_ID), anyString(), eq(8), eq(300)))
|
.thenReturn(0);
|
|
job.process(task);
|
|
verify(versions, never()).selectByTenantAndId(anyString(), any());
|
verify(fileApi, never()).generate(anyString(), any());
|
}
|
|
@Test
|
void generatesAndCompletesClaimedTask() {
|
DmsPdfGenerationTask task = task(0);
|
DmsFileVersionEntity version = version(CHECKSUM);
|
DmsFileObjectEntity object = object();
|
DmsPersistentPdfGenerateVO pdf = new DmsPersistentPdfGenerateVO();
|
pdf.setObjectKey("dms-derived/pdf/" + VERSION_ID + "/" + CHECKSUM + ".pdf");
|
pdf.setSizeBytes(128L);
|
pdf.setChecksumSha256("b".repeat(64));
|
pdf.setSourceChecksumSha256(CHECKSUM);
|
ActionResult<DmsPersistentPdfGenerateVO> response = new ActionResult<>();
|
response.setCode(200);
|
response.setData(pdf);
|
when(tasks.claim(eq(TENANT), eq(VERSION_ID), anyString(), eq(8), eq(300)))
|
.thenReturn(1);
|
when(versions.selectByTenantAndId(TENANT, VERSION_ID)).thenReturn(version);
|
when(objects.selectByTenantAndFileVersionId(TENANT, VERSION_ID)).thenReturn(object);
|
when(fileApi.generate(eq("jnpf-dms"), any())).thenReturn(response);
|
|
job.process(task);
|
|
verify(completion).succeed(eq(task), anyString(), eq(pdf));
|
verify(tasks, never()).fail(anyString(), any(), anyString(), anyString(),
|
org.mockito.ArgumentMatchers.anyInt(), org.mockito.ArgumentMatchers.anyBoolean());
|
}
|
|
@Test
|
void retriesWhenSourceChecksumChanged() {
|
DmsPdfGenerationTask task = task(0);
|
when(tasks.claim(eq(TENANT), eq(VERSION_ID), anyString(), eq(8), eq(300)))
|
.thenReturn(1);
|
when(versions.selectByTenantAndId(TENANT, VERSION_ID))
|
.thenReturn(version("c".repeat(64)));
|
when(objects.selectByTenantAndFileVersionId(TENANT, VERSION_ID)).thenReturn(object());
|
|
job.process(task);
|
|
verify(tasks).fail(eq(TENANT), eq(VERSION_ID), anyString(),
|
eq("持久化 PDF 源文件不存在或已变化"), eq(60), eq(false));
|
verify(fileApi, never()).generate(anyString(), any());
|
}
|
|
@Test
|
void marksTaskFailedAfterLastAttempt() {
|
DmsPdfGenerationTask task = task(7);
|
when(tasks.claim(eq(TENANT), eq(VERSION_ID), anyString(), eq(8), eq(300)))
|
.thenReturn(1);
|
when(versions.selectByTenantAndId(TENANT, VERSION_ID)).thenReturn(version(CHECKSUM));
|
when(objects.selectByTenantAndFileVersionId(TENANT, VERSION_ID)).thenReturn(object());
|
when(fileApi.generate(eq("jnpf-dms"), any())).thenThrow(new IllegalStateException("timeout"));
|
|
job.process(task);
|
|
verify(tasks).fail(eq(TENANT), eq(VERSION_ID), anyString(), eq("timeout"),
|
eq(21600), eq(true));
|
}
|
|
private DmsPdfGenerationTask task(int attempts) {
|
DmsPdfGenerationTask task = new DmsPdfGenerationTask();
|
task.setTenantId(TENANT);
|
task.setFileVersionId(VERSION_ID);
|
task.setSourceChecksumSha256(CHECKSUM);
|
task.setAttempts(attempts);
|
return task;
|
}
|
|
private DmsFileVersionEntity version(String checksum) {
|
DmsFileVersionEntity version = new DmsFileVersionEntity();
|
version.setId(VERSION_ID);
|
version.setTenantId(TENANT);
|
version.setFileName("quality.docx");
|
version.setMimeType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
version.setSizeBytes(1024L);
|
version.setChecksumSha256(checksum);
|
return version;
|
}
|
|
private DmsFileObjectEntity object() {
|
DmsFileObjectEntity object = new DmsFileObjectEntity();
|
object.setFileVersionId(VERSION_ID);
|
object.setTenantId(TENANT);
|
object.setStoragePlatform("seaweedfs-1");
|
object.setBucketName("jnpf-dms");
|
object.setBasePath("");
|
object.setObjectPath("dms/source/");
|
object.setObjectName("quality.docx");
|
return object;
|
}
|
|
private void set(String fieldName, Object value) throws Exception {
|
Field field = DmsPdfGenerationJob.class.getDeclaredField(fieldName);
|
field.setAccessible(true);
|
field.set(job, value);
|
}
|
}
|