This commit is contained in:
luke 2025-06-21 22:02:55 +08:00
parent 9670477f51
commit b82f44543e
10 changed files with 93 additions and 17 deletions

View File

@ -41,4 +41,11 @@ public interface DocAppService {
* 保存上传记录 * 保存上传记录
*/ */
void saveOSUplodRecord(OSRecordDTO dto); void saveOSUplodRecord(OSRecordDTO dto);
/**
* 将同路径下上传的历史同名文件全部抛弃
* @param localRelaFilePath
* @param latestMillis --- 最新版本文件的上传时间毫秒
*/
int markOldSearchableRecordsAsDiscarded(String localRelaFilePath, long latestMillis);
} }

View File

@ -3,6 +3,7 @@ package com.knowledge.base.application.service;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.knowledge.base.application.exceptions.AppException; import com.knowledge.base.application.exceptions.AppException;
import com.knowledge.base.domain.common.enums.SearchableStatusEnum;
import com.knowledge.base.domain.common.model.PageResult; import com.knowledge.base.domain.common.model.PageResult;
import com.knowledge.base.domain.doc.model.OSRecordDO; import com.knowledge.base.domain.doc.model.OSRecordDO;
import com.knowledge.base.domain.doc.service.iface.FileDomainService; import com.knowledge.base.domain.doc.service.iface.FileDomainService;
@ -119,4 +120,10 @@ public class DocAppServiceImpl implements DocAppService{
throw new AppException("保存对象存储记录失败!", e); throw new AppException("保存对象存储记录失败!", e);
} }
} }
@Override
public int markOldSearchableRecordsAsDiscarded(String localRelaFilePath, long latestMillis) {
return fileDomainService.updateOldSearchableRecordsByRelaPathAndTime(localRelaFilePath, latestMillis,
SearchableStatusEnum.SUCCESS.code, SearchableStatusEnum.DISCARDED.code);
}
} }

View File

@ -8,6 +8,7 @@ public enum SearchableStatusEnum {
INIT(0, "未开始进行导入"), INIT(0, "未开始进行导入"),
SUCCESS(1, "成功"), SUCCESS(1, "成功"),
FAILED(2, "导入失败"), FAILED(2, "导入失败"),
DISCARDED(3, "已过期,改文件不允许被检索;同人当天多次上次同名文件会进入该状态"),
PROHIBITED(99, "用户禁止文件被检索"), PROHIBITED(99, "用户禁止文件被检索"),
; ;

View File

@ -28,10 +28,21 @@ public interface OSRecordRepository {
/** /**
* 更新上传记录中文档的可搜索状态 * 更新上传记录中文档的可搜索状态
* @param localRelaFilePath * @param localRelaFilePath
* @param searchableStatus * @param oldSearchableStatus --- 为空时表示所有数据都需要更新
* @param newSearchableStatus
* @return * @return
*/ */
boolean updateSearchableStatusByRelaPath(String localRelaFilePath, int searchableStatus); boolean updateSearchableStatusByRelaPath(String localRelaFilePath, Integer oldSearchableStatus, int newSearchableStatus);
/**
* 跟新latestMills时间戳之前的记录可搜索状态为searchableStatus
* @param localRelaFilePath
* @param oldSearchableStatus --- 为空时表示所有数据都需要更新
* @param newSearchableStatus
* @param latestMills
* @return
*/
int updateOldSearchableRecordsByRelaPathAndTime(String localRelaFilePath, long latestMills, Integer oldSearchableStatus, int newSearchableStatus);
/** /**
* 批量获取 * 批量获取

View File

@ -35,10 +35,21 @@ public interface FileDomainService {
/** /**
* 更新上传记录中文档的可搜索状态 * 更新上传记录中文档的可搜索状态
* @param localRelaFilePath * @param localRelaFilePath
* @param searchableStatus * @param oldSearchableStatus
* @param newSearchableStatus
* @return * @return
*/ */
boolean updateSearchableStatusByRelaPath(String localRelaFilePath, int searchableStatus); boolean updateSearchableStatusByRelaPath(String localRelaFilePath, Integer oldSearchableStatus, int newSearchableStatus);
/**
* 跟新latestMills时间戳之前的记录可搜索状态为searchableStatus
* @param localRelaFilePath
* @param oldSearchableStatus --- 为空时表示所有数据都需要更新
* @param newSearchableStatus
* @param latestMills
* @return
*/
int updateOldSearchableRecordsByRelaPathAndTime(String localRelaFilePath, long latestMills, Integer oldSearchableStatus, int newSearchableStatus);
/** /**
* 批量获取上传记录 * 批量获取上传记录

View File

@ -147,7 +147,7 @@ public abstract class AbstractBaseFileImporter implements DocumentImporter {
// === Step 6: 写入 Elasticsearch 并更新 导入状态&缓存 === // === Step 6: 写入 Elasticsearch 并更新 导入状态&缓存 ===
boolean saved = esGateway.saveDoc(fileEsModel); boolean saved = esGateway.saveDoc(fileEsModel);
logger.info("导入结束: relativePah: {}, status: {}", localRelaFilePath, saved); logger.info("导入结束: relativePah: {}, status: {}", localRelaFilePath, saved);
fileDomainService.updateSearchableStatusByRelaPath(localRelaFilePath, saved ? SearchableStatusEnum.SUCCESS.code : SearchableStatusEnum.FAILED.code); fileDomainService.updateSearchableStatusByRelaPath(localRelaFilePath, SearchableStatusEnum.INIT.code, saved ? SearchableStatusEnum.SUCCESS.code : SearchableStatusEnum.FAILED.code);
String metaJson = transToMetaJson(BeanUtil.beanToMap(fileEsModel, false, true)); String metaJson = transToMetaJson(BeanUtil.beanToMap(fileEsModel, false, true));
fileCacheService.cacheMeta(localRelaFilePath, metaJson, ConstantConfig.FILE_META_CACHE_EXPIRED_MINUTES); fileCacheService.cacheMeta(localRelaFilePath, metaJson, ConstantConfig.FILE_META_CACHE_EXPIRED_MINUTES);

View File

@ -72,15 +72,17 @@ public class FileDomainServiceImpl implements FileDomainService {
return Optional.empty(); return Optional.empty();
} }
Optional<OSRecord> osRecordOpt = osRecordRepository.getLatestRecordByRelaPath(localRelaFilePath); Optional<OSRecord> osRecordOpt = osRecordRepository.getLatestRecordByRelaPath(localRelaFilePath);
if(osRecordOpt.isEmpty()) { return osRecordOpt.map(osRecord -> BeanConvertUtil.convert(osRecord, OSRecordDO.class));
return Optional.empty();
}
return Optional.of(BeanConvertUtil.convert(osRecordOpt.get(), OSRecordDO.class));
} }
@Override @Override
public boolean updateSearchableStatusByRelaPath(String localRelaFilePath, int searchableStatus) { public boolean updateSearchableStatusByRelaPath(String localRelaFilePath, Integer oldSearchableStatus, int newSearchableStatus) {
return osRecordRepository.updateSearchableStatusByRelaPath(localRelaFilePath, searchableStatus); return osRecordRepository.updateSearchableStatusByRelaPath(localRelaFilePath, oldSearchableStatus, newSearchableStatus);
}
@Override
public int updateOldSearchableRecordsByRelaPathAndTime(String localRelaFilePath, long latestMills, Integer oldSearchableStatus, int newSearchableStatus) {
return osRecordRepository.updateOldSearchableRecordsByRelaPathAndTime(localRelaFilePath, latestMills, oldSearchableStatus, newSearchableStatus);
} }
@Override @Override

View File

@ -229,6 +229,9 @@ public class FileWriteController {
Path targetPath = Paths.get(localDir, originFileNameWithSuffix); Path targetPath = Paths.get(localDir, originFileNameWithSuffix);
Files.write(targetPath, fileBytes); Files.write(targetPath, fileBytes);
// 根据localRelaFilePath删除可搜索的文件历史记录仅保存最近的一条初始状态的数据
docAppService.markOldSearchableRecordsAsDiscarded(localRelaFilePath, DateUtil.toMillis(now));
// 直接导入ES // 直接导入ES
Map<String, Object> extInfo = Map.of( Map<String, Object> extInfo = Map.of(
DocMetaPropEnum.UPLOADER.code, uploader, DocMetaPropEnum.UPLOADER.code, uploader,

View File

@ -14,7 +14,9 @@ import com.knowledge.base.infrastructure.repository.mapper.doc.OSRecordMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
@Repository @Repository
@ -44,22 +46,49 @@ public class OSRecordRepositoryImpl implements OSRecordRepository {
@Override @Override
public Optional<OSRecord> getLatestRecordByRelaPath(String localRelaFilePath) { public Optional<OSRecord> getLatestRecordByRelaPath(String localRelaFilePath) {
OSRecord fileLatestRecord = osRecordMapper.selectOne( List<OSRecord> records = osRecordMapper.selectList(
new QueryWrapper<OSRecord>() new QueryWrapper<OSRecord>()
.eq("local_rela_file_path", localRelaFilePath) .eq("local_rela_file_path", localRelaFilePath)
.orderByDesc("upload_time")); .orderByDesc("upload_time")
return Optional.ofNullable(fileLatestRecord); .last("LIMIT 1")
);
return records.stream().findFirst();
} }
@Override @Override
public boolean updateSearchableStatusByRelaPath(String localRelaFilePath, int searchableStatus) { public boolean updateSearchableStatusByRelaPath(String localRelaFilePath, Integer oldSearchableStatus, int newSearchableStatus) {
UpdateWrapper<OSRecord> updateWrapper = new UpdateWrapper<>(); UpdateWrapper<OSRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("local_rela_file_path", localRelaFilePath) if(Objects.nonNull(oldSearchableStatus)) {
.set("searchable_status", searchableStatus); updateWrapper.eq("local_rela_file_path", localRelaFilePath)
.eq("searchable_status", oldSearchableStatus)
.set("searchable_status", newSearchableStatus);
} else {
updateWrapper.eq("local_rela_file_path", localRelaFilePath)
.set("searchable_status", newSearchableStatus);
}
int rows = osRecordMapper.update(null, updateWrapper); int rows = osRecordMapper.update(null, updateWrapper);
return rows > 0; return rows > 0;
} }
@Override
public int updateOldSearchableRecordsByRelaPathAndTime(String localRelaFilePath, long latestMills, Integer oldSearchableStatus, int newSearchableStatus) {
UpdateWrapper<OSRecord> updateWrapper = new UpdateWrapper<>();
if(oldSearchableStatus != null) {
updateWrapper.eq("local_rela_file_path", localRelaFilePath)
.eq("searchable_status", oldSearchableStatus) // 筛选旧状态
.lt("upload_time", new Date(latestMills)) // upload_time 要小于当前 millis
.set("searchable_status", newSearchableStatus); // 设置为新状态
} else {
updateWrapper.eq("local_rela_file_path", localRelaFilePath)
.lt("upload_time", new Date(latestMills)) // upload_time 要小于当前 millis
.set("searchable_status", newSearchableStatus); // 设置为新状态
}
return osRecordMapper.update(null, updateWrapper);
}
@Override @Override
public List<OSRecord> batchQueryOSRecord(List<Long> recordIds) { public List<OSRecord> batchQueryOSRecord(List<Long> recordIds) {

View File

@ -9,6 +9,11 @@ import java.time.ZoneId;
*/ */
public class DateUtil { public class DateUtil {
/**
* 转毫秒
* @param time
* @return
*/
public static long toMillis(LocalDateTime time) { public static long toMillis(LocalDateTime time) {
return time.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); return time.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli();
} }