@@ -226,34 +226,50 @@ public DatasetFile getDatasetFile(Dataset dataset, String fileId, String prefix)
226226
227227 /**
228228 * 删除文件
229+ * 使用悲观锁防止并发删除导致 fileCount 计算不准确
229230 */
230231 @ Transactional
231232 public void deleteDatasetFile (String datasetId , String fileId , String prefix ) {
232- Dataset dataset = datasetRepository .getById (datasetId );
233+ // 使用悲观锁获取 dataset,确保并发安全
234+ Dataset dataset = datasetRepository .getByIdWithLock (datasetId );
233235 DatasetFile file = getDatasetFile (dataset , fileId , prefix );
234- dataset .setFiles (new ArrayList <>(Collections .singleton (file )));
236+
237+ // 先删除数据库记录
235238 datasetFileRepository .removeById (fileId );
236- if (CommonUtils .isUUID (fileId )) {
237- dataset .removeFile (file );
238- }
239- datasetRepository .updateById (dataset );
240- // 删除文件时,上传到数据集中的文件会同时删除数据库中的记录和文件系统中的文件,归集过来的文件仅删除数据库中的记录
239+
240+ // 删除物理文件(仅删除在数据集路径下的文件)
241241 if (file .getFilePath ().startsWith (dataset .getPath ())) {
242242 try {
243243 Path filePath = validateAndResolvePath (file .getFilePath (), dataset .getPath ());
244244 Files .deleteIfExists (filePath );
245245 } catch (IOException ex ) {
246+ log .error ("删除物理文件失败: {}" , file .getFilePath (), ex );
246247 throw BusinessException .of (SystemErrorCode .FILE_SYSTEM_ERROR );
247248 }
248249 }
250+
251+ // 重新计算文件统计信息(确保数据准确)
252+ List <DatasetFile > remainingFiles = datasetFileRepository .findAllByDatasetId (datasetId );
253+ dataset .setFileCount ((long ) remainingFiles .size ());
254+ dataset .setSizeBytes (remainingFiles .stream ()
255+ .mapToLong (f -> f .getFileSize () != null ? f .getFileSize ().longValue () : 0L )
256+ .sum ());
257+ dataset .setUpdatedAt (LocalDateTime .now ());
258+
259+ datasetRepository .updateById (dataset );
260+
261+ log .info ("删除文件成功 - datasetId: {}, fileId: {}, fileName: {}, fileCount: {}, sizeBytes: {}" ,
262+ datasetId , fileId , file .getFileName (), dataset .getFileCount (), dataset .getSizeBytes ());
249263 }
250264
251265 /**
252266 * 批量删除文件
267+ * 使用悲观锁防止并发删除导致 fileCount 计算不准确
253268 */
254269 @ Transactional
255270 public void batchDeleteFiles (String datasetId , BatchDeleteFilesRequest request ) {
256- Dataset dataset = datasetRepository .getById (datasetId );
271+ // 使用悲观锁获取 dataset,确保并发安全
272+ Dataset dataset = datasetRepository .getByIdWithLock (datasetId );
257273 if (dataset == null ) {
258274 throw BusinessException .of (DataManagementErrorCode .DATASET_NOT_FOUND );
259275 }
@@ -266,6 +282,7 @@ public void batchDeleteFiles(String datasetId, BatchDeleteFilesRequest request)
266282 List <DatasetFile > filesToDelete = new ArrayList <>();
267283 List <String > failedFileIds = new ArrayList <>();
268284
285+ // 先删除数据库记录
269286 for (String fileId : fileIds ) {
270287 try {
271288 DatasetFile file = getDatasetFile (dataset , fileId , request .getPrefix ());
@@ -277,20 +294,8 @@ public void batchDeleteFiles(String datasetId, BatchDeleteFilesRequest request)
277294 }
278295 }
279296
280- // 更新数据集(避免 ConcurrentModificationException)
281- List <DatasetFile > datasetFiles = dataset .getFiles ();
282- if (datasetFiles != null ) {
283- // 创建一个新的列表来存储要保留的文件
284- List <DatasetFile > remainingFiles = new ArrayList <>(datasetFiles );
285- // 移除要删除的文件
286- remainingFiles .removeAll (filesToDelete );
287- dataset .setFiles (remainingFiles );
288- }
289- datasetRepository .updateById (dataset );
290-
291- // 删除文件系统中的文件
297+ // 删除物理文件(仅删除在数据集路径下的文件)
292298 for (DatasetFile file : filesToDelete ) {
293- // 上传到数据集中的文件会同时删除数据库中的记录和文件系统中的文件,归集过来的文件仅删除数据库中的记录
294299 if (file .getFilePath ().startsWith (dataset .getPath ())) {
295300 try {
296301 Path filePath = validateAndResolvePath (file .getFilePath (), dataset .getPath ());
@@ -303,6 +308,19 @@ public void batchDeleteFiles(String datasetId, BatchDeleteFilesRequest request)
303308 }
304309 }
305310
311+ // 重新计算文件统计信息(确保数据准确)
312+ List <DatasetFile > remainingFiles = datasetFileRepository .findAllByDatasetId (datasetId );
313+ dataset .setFileCount ((long ) remainingFiles .size ());
314+ dataset .setSizeBytes (remainingFiles .stream ()
315+ .mapToLong (f -> f .getFileSize () != null ? f .getFileSize ().longValue () : 0L )
316+ .sum ());
317+ dataset .setUpdatedAt (LocalDateTime .now ());
318+
319+ datasetRepository .updateById (dataset );
320+
321+ log .info ("批量删除文件成功 - datasetId: {}, successCount: {}, failedCount: {}, fileCount: {}, sizeBytes: {}" ,
322+ datasetId , filesToDelete .size (), failedFileIds .size (), dataset .getFileCount (), dataset .getSizeBytes ());
323+
306324 // 如果有失败的文件,记录日志但不抛出异常
307325 if (!failedFileIds .isEmpty ()) {
308326 log .warn ("Failed to delete {} files out of {}" , failedFileIds .size (), fileIds .size ());
@@ -643,7 +661,8 @@ private void zipDirectory(Path sourceDir, Path basePath, ZipArchiveOutputStream
643661 */
644662 @ Transactional
645663 public void deleteDirectory (String datasetId , String prefix ) {
646- Dataset dataset = datasetRepository .getById (datasetId );
664+ // 使用悲观锁获取 dataset,防止并发删除导致 fileCount 不准确
665+ Dataset dataset = datasetRepository .getByIdWithLock (datasetId );
647666 if (dataset == null ) {
648667 throw BusinessException .of (DataManagementErrorCode .DATASET_NOT_FOUND );
649668 }
@@ -694,6 +713,10 @@ public void deleteDirectory(String datasetId, String prefix) {
694713 })
695714 .collect (Collectors .toList ());
696715
716+ log .info ("删除目录开始 - datasetId: {}, prefix: {}, fileCount: {}, filesToDelete: {}" ,
717+ datasetId , prefix , dataset .getFileCount (), filesToDelete .size ());
718+
719+ // 删除数据库记录
697720 for (DatasetFile file : filesToDelete ) {
698721 datasetFileRepository .removeById (file .getId ());
699722 }
@@ -702,20 +725,22 @@ public void deleteDirectory(String datasetId, String prefix) {
702725 try {
703726 deleteDirectoryRecursively (normalized );
704727 } catch (IOException e ) {
705- log .error ("Failed to delete directory {} for dataset {}" , normalized , datasetId , e );
728+ log .error ("删除目录失败: datasetId={}, prefix= {}" , datasetId , prefix , e );
706729 throw BusinessException .of (SystemErrorCode .FILE_SYSTEM_ERROR );
707730 }
708731
709- // 更新数据集(避免 ConcurrentModificationException,先获取文件列表再删除)
710- List <DatasetFile > datasetFiles = dataset .getFiles ();
711- if (datasetFiles != null ) {
712- // 创建一个新的列表来存储要保留的文件
713- List <DatasetFile > remainingFiles = new ArrayList <>(datasetFiles );
714- // 移除要删除的文件
715- remainingFiles .removeAll (filesToDelete );
716- dataset .setFiles (remainingFiles );
717- }
732+ // 重新计算文件统计信息(确保数据准确)
733+ List <DatasetFile > remainingFiles = datasetFileRepository .findAllByDatasetId (datasetId );
734+ dataset .setFileCount ((long ) remainingFiles .size ());
735+ dataset .setSizeBytes (remainingFiles .stream ()
736+ .mapToLong (f -> f .getFileSize () != null ? f .getFileSize ().longValue () : 0L )
737+ .sum ());
738+ dataset .setUpdatedAt (LocalDateTime .now ());
739+
718740 datasetRepository .updateById (dataset );
741+
742+ log .info ("删除目录成功 - datasetId: {}, prefix: {}, deletedCount: {}, fileCount: {}, sizeBytes: {}" ,
743+ datasetId , prefix , filesToDelete .size (), dataset .getFileCount (), dataset .getSizeBytes ());
719744 }
720745
721746 /**
0 commit comments