解决节点删除问题
This commit is contained in:
parent
f4f7511603
commit
594c4d4189
@ -253,6 +253,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
FileItemResult fileItemResult = fileService.getFileItem(path);
|
FileItemResult fileItemResult = fileService.getFileItem(path);
|
||||||
if (fileItemResult == null || fileItemResult.getName() == null) {
|
if (fileItemResult == null || fileItemResult.getName() == null) {
|
||||||
LOGGER.error("{}文件没有上传到工作空间,请重新选择上传", fileNameData);
|
LOGGER.error("{}文件没有上传到工作空间,请重新选择上传", fileNameData);
|
||||||
|
// 跳过处理这个文件,避免空指针异常
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
tsFiles.setUrl(fileItemResult.getUrl());
|
tsFiles.setUrl(fileItemResult.getUrl());
|
||||||
//如果是压缩文件 类型就给zip
|
//如果是压缩文件 类型就给zip
|
||||||
@ -260,7 +262,12 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
if (isValid) {
|
if (isValid) {
|
||||||
tsFiles.setType("ZIP");
|
tsFiles.setType("ZIP");
|
||||||
} else {
|
} else {
|
||||||
tsFiles.setType(fileItemResult.getType().getValue());
|
// 添加空值检查,防止空指针异常
|
||||||
|
if (fileItemResult.getType() != null) {
|
||||||
|
tsFiles.setType(fileItemResult.getType().getValue());
|
||||||
|
} else {
|
||||||
|
tsFiles.setType("UNKNOWN");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tsFiles.getUpdateTime() == null) {
|
if (tsFiles.getUpdateTime() == null) {
|
||||||
tsFiles.setUpdateTime(tsFiles.getUploadTime());
|
tsFiles.setUpdateTime(tsFiles.getUploadTime());
|
||||||
|
|||||||
@ -551,51 +551,74 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
|
|||||||
@Override
|
@Override
|
||||||
public boolean deleteTstaskByIds(List<String> dataset) {
|
public boolean deleteTstaskByIds(List<String> dataset) {
|
||||||
Boolean value = false;
|
Boolean value = false;
|
||||||
|
|
||||||
|
LOGGER.info("开始批量删除试验任务,任务数量: {}", dataset.size());
|
||||||
|
LOGGER.debug("待删除的任务ID列表: {}", dataset);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//循环所有的ID
|
//循环所有的ID
|
||||||
for (String taskId : dataset) {
|
for (String taskId : dataset) {
|
||||||
try {
|
try {
|
||||||
|
LOGGER.info("开始处理任务删除,任务ID: {}", taskId);
|
||||||
|
|
||||||
//获取试验任务及任务编码
|
//获取试验任务及任务编码
|
||||||
TsTask tsTask = tsTaskMapper.selectById(taskId);
|
TsTask tsTask = tsTaskMapper.selectById(taskId);
|
||||||
|
if (tsTask == null) {
|
||||||
|
LOGGER.warn("未找到指定的任务,任务ID: {}", taskId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
|
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
|
||||||
|
LOGGER.debug("设置任务编码上下文,任务编码: {}", tsTask.getTaskCode());
|
||||||
|
|
||||||
// 删除节点表
|
// 删除节点表
|
||||||
LambdaQueryWrapper<TsNodes> deleteWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<TsNodes> deleteWrapper = new LambdaQueryWrapper<>();
|
||||||
deleteWrapper.eq(TsNodes::getTaskId, taskId);
|
deleteWrapper.eq(TsNodes::getTaskId, taskId);
|
||||||
tsNodesMapper.delete(deleteWrapper);
|
int deletedNodes = tsNodesMapper.delete(deleteWrapper);
|
||||||
|
LOGGER.info("删除任务相关的节点数据,任务ID: {}, 删除条数: {}", taskId, deletedNodes);
|
||||||
|
|
||||||
// 删除文件表
|
// 只有当任务文件表存在时才尝试删除文件数据
|
||||||
LambdaQueryWrapper<TsFiles> deleteWrapperFiles = new LambdaQueryWrapper<>();
|
if (tableExists("ts_files_" + tsTask.getTaskCode())) {
|
||||||
deleteWrapperFiles.eq(TsFiles::getTaskId, taskId);
|
// 删除文件表
|
||||||
tsFilesMapper.delete(deleteWrapperFiles);
|
LambdaQueryWrapper<TsFiles> deleteWrapperFiles = new LambdaQueryWrapper<>();
|
||||||
|
deleteWrapperFiles.eq(TsFiles::getTaskId, taskId);
|
||||||
|
int deletedFiles = tsFilesMapper.delete(deleteWrapperFiles);
|
||||||
|
LOGGER.info("删除任务相关的文件数据,任务ID: {}, 删除条数: {}", taskId, deletedFiles);
|
||||||
|
} else {
|
||||||
|
LOGGER.info("任务文件表不存在,跳过文件数据删除,任务ID: {}", taskId);
|
||||||
|
}
|
||||||
|
|
||||||
// 删除本地存储空间中的文件夹
|
// 删除本地存储空间中的文件夹
|
||||||
StorageSource localStorageSource = getStorageConfig(tsTask.getLocalStorageId());
|
StorageSource localStorageSource = getStorageConfig(tsTask.getLocalStorageId());
|
||||||
|
LOGGER.info("开始删除本地存储空间中的文件夹,任务ID: {}, 本地存储ID: {}", taskId, tsTask.getLocalStorageId());
|
||||||
deleteStorageFolder(localStorageSource, tsTask);
|
deleteStorageFolder(localStorageSource, tsTask);
|
||||||
|
|
||||||
// 如果有备份存储空间,也删除备份存储空间中的文件夹
|
// 如果有备份存储空间,也删除备份存储空间中的文件夹
|
||||||
if (tsTask.getBackupStorageId() != null && tsTask.getBackupStorageId() > 0) {
|
if (tsTask.getBackupStorageId() != null && tsTask.getBackupStorageId() > 0) {
|
||||||
StorageSource backupStorageSource = getStorageConfig(tsTask.getBackupStorageId());
|
StorageSource backupStorageSource = getStorageConfig(tsTask.getBackupStorageId());
|
||||||
|
LOGGER.info("开始删除备份存储空间中的文件夹,任务ID: {}, 备份存储ID: {}", taskId, tsTask.getBackupStorageId());
|
||||||
deleteStorageFolder(backupStorageSource, tsTask);
|
deleteStorageFolder(backupStorageSource, tsTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除当前试验任务
|
// 删除当前试验任务
|
||||||
int deleteCount = tsTaskMapper.deleteById(taskId);
|
int deleteCount = tsTaskMapper.deleteById(taskId);
|
||||||
if (deleteCount == 1) {
|
if (deleteCount == 1) {
|
||||||
LOGGER.info("tstask表结构删除成功");
|
LOGGER.info("试验任务删除成功,任务ID: {}", taskId);
|
||||||
value = true;
|
value = true;
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("tstask表结构删除失败");
|
LOGGER.error("试验任务删除失败,任务ID: {}, 实际删除条数: {}", taskId, deleteCount);
|
||||||
value = false;
|
value = false;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// 每次处理完一个任务后清理上下文
|
// 每次处理完一个任务后清理上下文
|
||||||
|
LOGGER.debug("清理任务上下文,任务ID: {}", taskId);
|
||||||
TableNameContextHolder.clear();
|
TableNameContextHolder.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOGGER.info("批量删除试验任务完成,任务数量: {}", dataset.size());
|
||||||
return value;
|
return value;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.error("删除试验任务时发生异常", e);
|
LOGGER.error("删除试验任务时发生异常,任务ID列表: {}", dataset, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,7 +627,20 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
|
|||||||
// 这个方法会递归删除试验任务文件夹及其下的所有子文件夹和文件。当调用 fileService.deleteFolder() 方法时,存储服务实现会自动处理递归删除逻辑,确保整个文件夹树都被清除。
|
// 这个方法会递归删除试验任务文件夹及其下的所有子文件夹和文件。当调用 fileService.deleteFolder() 方法时,存储服务实现会自动处理递归删除逻辑,确保整个文件夹树都被清除。
|
||||||
//这是文件存储系统的基本特性,不论是本地文件系统还是MinIO等云存储服务,在删除文件夹时都会删除其包含的所有内容。
|
//这是文件存储系统的基本特性,不论是本地文件系统还是MinIO等云存储服务,在删除文件夹时都会删除其包含的所有内容。
|
||||||
private void deleteStorageFolder(StorageSource storageSource, TsTask tsTask) {
|
private void deleteStorageFolder(StorageSource storageSource, TsTask tsTask) {
|
||||||
|
LOGGER.info("==deleteStorageFolder begin====");
|
||||||
|
if (storageSource == null) {
|
||||||
|
LOGGER.warn("存储源配置为空,跳过删除操作,任务名称: {}", tsTask.getTaskName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsTask == null || tsTask.getTaskName() == null) {
|
||||||
|
LOGGER.warn("任务信息不完整,跳过删除操作");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
LOGGER.info("准备删除存储文件夹,存储类型: {}, 任务名称: {}", storageSource.getKey(), tsTask.getTaskName());
|
||||||
|
|
||||||
List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>();
|
List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>();
|
||||||
BatchDeleteRequest.DeleteItem deleteItemData = new BatchDeleteRequest.DeleteItem();
|
BatchDeleteRequest.DeleteItem deleteItemData = new BatchDeleteRequest.DeleteItem();
|
||||||
deleteItemData.setName(tsTask.getTaskName());
|
deleteItemData.setName(tsTask.getTaskName());
|
||||||
@ -616,33 +652,50 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
|
|||||||
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
|
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
|
||||||
batchDeleteRequest.setDeleteItems(deleteItemList);
|
batchDeleteRequest.setDeleteItems(deleteItemList);
|
||||||
batchDeleteRequest.setStorageKey(storageSource.getKey());
|
batchDeleteRequest.setStorageKey(storageSource.getKey());
|
||||||
|
|
||||||
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
|
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
|
||||||
|
if (fileService == null) {
|
||||||
|
LOGGER.error("未能获取到文件服务实例,存储类型: {}", storageSource.getKey());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int deleteSuccessCount = 0;
|
int deleteSuccessCount = 0;
|
||||||
for (BatchDeleteRequest.DeleteItem deleteItem : deleteItemList) {
|
for (BatchDeleteRequest.DeleteItem deleteItem : deleteItemList) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
try {
|
try {
|
||||||
if (deleteItem.getType() == FileTypeEnum.FILE) {
|
if (deleteItem.getType() == FileTypeEnum.FILE) {
|
||||||
|
LOGGER.info("删除文件,存储类型: {}, 路径: {}, 名称: {}",
|
||||||
|
storageSource.getKey(), deleteItem.getPath(), deleteItem.getName());
|
||||||
flag = fileService.deleteFile(deleteItem.getPath(), deleteItem.getName());
|
flag = fileService.deleteFile(deleteItem.getPath(), deleteItem.getName());
|
||||||
} else if (deleteItem.getType() == FileTypeEnum.FOLDER) {
|
} else if (deleteItem.getType() == FileTypeEnum.FOLDER) {
|
||||||
|
LOGGER.info("删除文件夹,存储类型: {}, 路径: {}, 名称: {}",
|
||||||
|
storageSource.getKey(), deleteItem.getPath(), deleteItem.getName());
|
||||||
flag = fileService.deleteFolder(deleteItem.getPath(), deleteItem.getName());
|
flag = fileService.deleteFolder(deleteItem.getPath(), deleteItem.getName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag) {
|
if (flag) {
|
||||||
deleteSuccessCount++;
|
deleteSuccessCount++;
|
||||||
LOGGER.info("删除成功 - 存储类型: {}, 类型: {}, 路径: {}, 名称: {}",
|
LOGGER.info("删除成功 - 存储类型: {}, 类型: {}, 路径: {}, 名称: {}",
|
||||||
storageSource.getKey(), deleteItem.getType(), deleteItem.getPath(), deleteItem.getName());
|
storageSource.getKey(), deleteItem.getType(), deleteItem.getPath(), deleteItem.getName());
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn("删除失败 - 存储类型: {}, 类型: {}, 路径: {}, 名称: {}",
|
LOGGER.warn("删除失败 - 存储类型: {}, 类型: {}, 路径: {}, 名称: {}",
|
||||||
storageSource.getKey(), deleteItem.getType(), deleteItem.getPath(), deleteItem.getName());
|
storageSource.getKey(), deleteItem.getType(), deleteItem.getPath(), deleteItem.getName());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.error("删除文件/文件夹失败, 存储类型: {}, 文件路径: {}, 文件名称: {}",
|
LOGGER.error("删除文件/文件夹失败, 存储类型: {}, 文件路径: {}, 文件名称: {}",
|
||||||
storageSource.getKey(), deleteItem.getPath(), deleteItem.getName(), e);
|
storageSource.getKey(), deleteItem.getPath(), deleteItem.getName(), e);
|
||||||
|
// 继续处理其他项目,不中断整个删除过程
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER.info("存储文件夹删除完成,存储类型: {}, 成功删除项数量: {}", storageSource.getKey(), deleteSuccessCount);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.error("删除存储空间文件夹时发生异常, 存储类型: {}", storageSource.getKey(), e);
|
LOGGER.error("删除存储空间文件夹时发生异常, 存储类型: {}", storageSource.getKey(), e);
|
||||||
|
} catch (Error err) {
|
||||||
|
// 捕获Error防止JVM退出
|
||||||
|
LOGGER.error("删除存储空间文件夹时发生严重错误, 存储类型: {}", storageSource.getKey(), err);
|
||||||
|
// 不重新抛出Error,防止Tomcat退出
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,19 +715,29 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
|
|||||||
boolean allDeletable = true;
|
boolean allDeletable = true;
|
||||||
|
|
||||||
for (TsTask tsTask : tsTasks) {
|
for (TsTask tsTask : tsTasks) {
|
||||||
|
// 检查对应的任务文件表是否存在
|
||||||
|
if (!tableExists("ts_files_" + tsTask.getTaskCode())) {
|
||||||
|
// 如果表不存在,可以安全删除
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
|
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
|
||||||
|
|
||||||
// 查询 backup_path 既不为 null 也不为空字符串的记录
|
try {
|
||||||
LambdaQueryWrapper<TsFiles> queryWrapper = new LambdaQueryWrapper<>();
|
// 查询 backup_path 既不为 null 也不为空字符串的记录
|
||||||
queryWrapper.eq(TsFiles::getTaskId, tsTask.getId())
|
LambdaQueryWrapper<TsFiles> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
.isNotNull(TsFiles::getBackupPath)
|
queryWrapper.eq(TsFiles::getTaskId, tsTask.getId())
|
||||||
.ne(TsFiles::getBackupPath, "");
|
.isNotNull(TsFiles::getBackupPath)
|
||||||
|
.ne(TsFiles::getBackupPath, "");
|
||||||
|
|
||||||
int count = tsFilesService.count(queryWrapper);
|
int count = tsFilesService.count(queryWrapper);
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
allDeletable = false;
|
allDeletable = false;
|
||||||
break; // 一旦发现不可删除项,提前终止循环
|
break; // 一旦发现不可删除项,提前终止循环
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
TableNameContextHolder.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,8 +748,6 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
|
|||||||
// 使用日志框架代替 printStackTrace
|
// 使用日志框架代替 printStackTrace
|
||||||
LOGGER.error("确认删除实验任务时发生异常", e);
|
LOGGER.error("确认删除实验任务时发生异常", e);
|
||||||
return ResponseResult.error("查询失败");
|
return ResponseResult.error("查询失败");
|
||||||
} finally {
|
|
||||||
TableNameContextHolder.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -165,7 +165,10 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
|
|||||||
checkPathSecurity(path);
|
checkPathSecurity(path);
|
||||||
checkNameSecurity(name);
|
checkNameSecurity(name);
|
||||||
|
|
||||||
String fullPath = StringUtils.concat(param.getFilePath(), path, name);
|
String fullPath = StringUtils.concatTrimStartSlashes(param.getFilePath(), name);
|
||||||
|
log.info("param.getFilePath==========,{}", param.getFilePath());
|
||||||
|
log.info("fullPath==========,{}", fullPath);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 检查文件夹是否存在
|
// 检查文件夹是否存在
|
||||||
File folder = new File(fullPath);
|
File folder = new File(fullPath);
|
||||||
@ -184,7 +187,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 递归修改文件夹内所有文件的权限
|
// 递归修改文件夹内所有文件的权限
|
||||||
setWritableRecursively(folder);
|
//setWritableRecursively(folder);
|
||||||
|
|
||||||
return FileUtil.del(fullPath);
|
return FileUtil.del(fullPath);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@ -17,6 +17,10 @@ spring:
|
|||||||
url: jdbc:mysql://db-container:3306/filemanagedb?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
url: jdbc:mysql://db-container:3306/filemanagedb?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||||
username: root
|
username: root
|
||||||
password: pwd@FileMgr
|
password: pwd@FileMgr
|
||||||
|
initial-size: 5
|
||||||
|
min-idle: 5
|
||||||
|
max-active: 20
|
||||||
|
validation-query: SELECT 1
|
||||||
mvc:
|
mvc:
|
||||||
pathmatch:
|
pathmatch:
|
||||||
matching-strategy: ant_path_matcher
|
matching-strategy: ant_path_matcher
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user