package jnpf.dmsService.expiry; import jnpf.dmsEntity.storage.expiry.DmsFileExpiryItem; import jnpf.dmsMapper.DmsFileExpiryMapper; import jnpf.dmsService.search.meili.DmsMeilisearchClient; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Slf4j @Service @RequiredArgsConstructor public class DmsFileExpirySearchCleanup { private final DmsFileExpiryMapper mapper; private final DmsMeilisearchClient client; private final DmsFileExpiryProperties properties; @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void process(DmsFileExpiryItem candidate) { DmsFileExpiryItem item = mapper.lockCleanup(candidate.getTenantId(), candidate.getFileVersionId()); if (item == null) return; boolean done = false; String error = null; try { if (item.getSearchTaskId() == null) { item.setSearchTaskId(client.deleteDocument(item.getTenantId(), item.getFileVersionId())); done = item.getSearchTaskId() == null; // Index does not exist. } else { String status = client.taskStatus(item.getSearchTaskId()); done = "succeeded".equals(status); if ("failed".equals(status) || "canceled".equals(status) || "missing".equals(status)) { item.setSearchTaskId(null); // Resubmit idempotent deletion on the next scan. error = "Meilisearch task " + status; } } } catch (Exception failure) { error = failure.getClass().getSimpleName() + ": " + failure.getMessage(); log.warn("DMS expiry index cleanup pending tenant={} version={}", item.getTenantId(), item.getFileVersionId(), failure); } mapper.updateCleanup(item, done, error == null ? null : error.substring(0, Math.min(1000, error.length())), Math.max(1, properties.getCleanupRetrySeconds())); } }