From 1782a16ea4412ced5cc90a25210eaad992013a31 Mon Sep 17 00:00:00 2001 From: Loporrit <141286461+loporrit@users.noreply.github.com> Date: Fri, 6 Sep 2024 08:54:19 +0000 Subject: [PATCH] Avoid race conditon between uploads and cleanup --- .../Services/FileCleanupService.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/Services/FileCleanupService.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/Services/FileCleanupService.cs index f65e6c5..dffbabc 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/Services/FileCleanupService.cs +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/Services/FileCleanupService.cs @@ -20,6 +20,7 @@ public class FileCleanupService : IHostedService private readonly bool _isMain = false; private readonly bool _isDistributionNode = false; private readonly bool _useColdStorage = false; + private HashSet _orphanedFiles = new(StringComparer.Ordinal); private CancellationTokenSource _cleanupCts; @@ -112,17 +113,29 @@ public class FileCleanupService : IHostedService private void CleanUpOrphanedFiles(HashSet allDbFileHashes, List allPhysicalFiles, CancellationToken ct) { + // To avoid race conditions with file uploads, only delete files on a second pass + var newOrphanedFiles = new HashSet(StringComparer.Ordinal); + foreach (var file in allPhysicalFiles.ToList()) { if (!allDbFileHashes.Contains(file.Name.ToUpperInvariant())) { - file.Delete(); - _logger.LogInformation("File not in DB, deleting: {fileName}", file.Name); - allPhysicalFiles.Remove(file); + _logger.LogInformation("File not in DB, marking: {fileName}", file.Name); + newOrphanedFiles.Add(file.FullName); } ct.ThrowIfCancellationRequested(); } + + foreach (var fullName in _orphanedFiles.Where(f => newOrphanedFiles.Contains(f))) + { + var name = Path.GetFileName(fullName); + File.Delete(fullName); + _logger.LogInformation("File still not in DB, deleting: {fileName}", name); + allPhysicalFiles.RemoveAll(f => f.FullName.Equals(fullName, StringComparison.InvariantCultureIgnoreCase)); + } + + _orphanedFiles = newOrphanedFiles; } private List CleanUpOutdatedFiles(List files, int unusedRetention, int forcedDeletionAfterHours, CancellationToken ct)