From a125b2ac0beda2ba890599eceafda05d6fa84109 Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Thu, 18 Mar 2021 14:18:56 -0500 Subject: [PATCH] Fixed GetInProgress API - The condition for PagesRead needed to be a sum for all progress, not each row. --- API/Data/SeriesRepository.cs | 11 ++--- .../ApplicationServiceExtensions.cs | 3 -- API/Interfaces/Services/IBackupService.cs | 2 + API/Interfaces/Services/IDirectoryService.cs | 1 + API/Services/DirectoryService.cs | 8 +++- API/Services/Tasks/BackupService.cs | 48 +++++++++++++++++++ API/Services/Tasks/CleanupService.cs | 8 +++- 7 files changed, 69 insertions(+), 12 deletions(-) diff --git a/API/Data/SeriesRepository.cs b/API/Data/SeriesRepository.cs index 8c1949edc..dbee172b9 100644 --- a/API/Data/SeriesRepository.cs +++ b/API/Data/SeriesRepository.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading.Tasks; using API.DTOs; using API.Entities; +using API.Extensions; using API.Helpers; using API.Interfaces; using AutoMapper; @@ -297,7 +298,7 @@ namespace API.Data } /// - /// + /// Returns Series that the user /// /// /// @@ -305,12 +306,11 @@ namespace API.Data /// public async Task> GetInProgress(int userId, int libraryId, int limit) { - //var twoWeeksAgo = DateTime.Today.Subtract(TimeSpan.FromDays(14)); // TODO: Think about moving this to a setting var series = await _context.Series .Join(_context.AppUserProgresses, s => s.Id, progress => progress.SeriesId, (s, progress) => new { Series = s, - progress.PagesRead, + PagesRead = _context.AppUserProgresses.Where(s1 => s1.SeriesId == s.Id).Sum(s1 => s1.PagesRead), progress.AppUserId, progress.LastModified }) @@ -320,12 +320,11 @@ namespace API.Data && (libraryId <= 0 || s.Series.LibraryId == libraryId) ) .Take(limit) .OrderByDescending(s => s.LastModified) - .AsNoTracking() .Select(s => s.Series) - .Distinct() .ProjectTo(_mapper.ConfigurationProvider) + .AsNoTracking() .ToListAsync(); - return series; + return series.DistinctBy(s => s.Name); } } } \ No newline at end of file diff --git a/API/Extensions/ApplicationServiceExtensions.cs b/API/Extensions/ApplicationServiceExtensions.cs index 6c5d4ec34..a9be9e0cb 100644 --- a/API/Extensions/ApplicationServiceExtensions.cs +++ b/API/Extensions/ApplicationServiceExtensions.cs @@ -5,9 +5,6 @@ using API.Interfaces.Services; using API.Services; using API.Services.Tasks; using AutoMapper; -using Hangfire; -using Hangfire.LiteDB; -using Hangfire.MemoryStorage; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; diff --git a/API/Interfaces/Services/IBackupService.cs b/API/Interfaces/Services/IBackupService.cs index 0f46a77c9..eaa140e46 100644 --- a/API/Interfaces/Services/IBackupService.cs +++ b/API/Interfaces/Services/IBackupService.cs @@ -13,5 +13,7 @@ namespace API.Interfaces.Services /// /// IEnumerable LogFiles(int maxRollingFiles, string logFileName); + + void CleanupBackups(); } } \ No newline at end of file diff --git a/API/Interfaces/Services/IDirectoryService.cs b/API/Interfaces/Services/IDirectoryService.cs index c4b15b94b..1437df69b 100644 --- a/API/Interfaces/Services/IDirectoryService.cs +++ b/API/Interfaces/Services/IDirectoryService.cs @@ -42,6 +42,7 @@ namespace API.Interfaces.Services void ClearDirectory(string directoryPath); bool CopyFilesToDirectory(IEnumerable filePaths, string directoryPath); + bool Exists(string directory); IEnumerable GetFiles(string path, string searchPatternExpression = "", SearchOption searchOption = SearchOption.TopDirectoryOnly); diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs index f1f4f5eb1..6ae953802 100644 --- a/API/Services/DirectoryService.cs +++ b/API/Services/DirectoryService.cs @@ -39,7 +39,13 @@ namespace API.Services .Where(file => reSearchPattern.IsMatch(Path.GetExtension(file))); } - + + public bool Exists(string directory) + { + var di = new DirectoryInfo(directory); + return di.Exists; + } + public IEnumerable GetFiles(string path, string searchPatternExpression = "", SearchOption searchOption = SearchOption.TopDirectoryOnly) { diff --git a/API/Services/Tasks/BackupService.cs b/API/Services/Tasks/BackupService.cs index 9642a0faa..ee8b3cf89 100644 --- a/API/Services/Tasks/BackupService.cs +++ b/API/Services/Tasks/BackupService.cs @@ -99,6 +99,54 @@ namespace API.Services.Tasks _directoryService.ClearAndDeleteDirectory(tempDirectory); _logger.LogInformation("Database backup completed"); } + + /// + /// Removes Database backups older than 30 days. If all backups are older than 30 days, the latest is kept. + /// + public void CleanupBackups() + { + const int dayThreshold = 30; + _logger.LogInformation("Beginning cleanup of Database backups at {Time}", DateTime.Now); + var backupDirectory = Task.Run(() => _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BackupDirectory)).Result.Value; + if (!_directoryService.Exists(backupDirectory)) return; + var deltaTime = DateTime.Today.Subtract(TimeSpan.FromDays(dayThreshold)); + var allBackups = _directoryService.GetFiles(backupDirectory).ToList(); + var expiredBackups = allBackups.Select(filename => new FileInfo(filename)) + .Where(f => f.CreationTime > deltaTime) + .ToList(); + if (expiredBackups.Count == allBackups.Count) + { + _logger.LogInformation("All expired backups are older than {Threshold} days. Removing all but last backup", dayThreshold); + var toDelete = expiredBackups.OrderByDescending(f => f.CreationTime).ToList(); + for (var i = 1; i < toDelete.Count; i++) + { + try + { + toDelete[i].Delete(); + } + catch (Exception ex) + { + _logger.LogError(ex, "There was an issue deleting {FileName}", toDelete[i].Name); + } + } + } + else + { + foreach (var file in expiredBackups) + { + try + { + file.Delete(); + } + catch (Exception ex) + { + _logger.LogError(ex, "There was an issue deleting {FileName}", file.Name); + } + } + + } + _logger.LogInformation("Finished cleanup of Database backups at {Time}", DateTime.Now); + } } } \ No newline at end of file diff --git a/API/Services/Tasks/CleanupService.cs b/API/Services/Tasks/CleanupService.cs index a33cf746f..a98e33cbf 100644 --- a/API/Services/Tasks/CleanupService.cs +++ b/API/Services/Tasks/CleanupService.cs @@ -13,12 +13,14 @@ namespace API.Services.Tasks private readonly ICacheService _cacheService; private readonly IDirectoryService _directoryService; private readonly ILogger _logger; + private readonly IBackupService _backupService; - public CleanupService(ICacheService cacheService, IDirectoryService directoryService, ILogger logger) + public CleanupService(ICacheService cacheService, IDirectoryService directoryService, ILogger logger, IBackupService backupService) { _cacheService = cacheService; _directoryService = directoryService; _logger = logger; + _backupService = backupService; } [AutomaticRetry(Attempts = 3, LogEvents = false, OnAttemptsExceeded = AttemptsExceededAction.Fail)] @@ -29,7 +31,9 @@ namespace API.Services.Tasks _directoryService.ClearDirectory(tempDirectory); _logger.LogInformation("Cleaning cache directory"); _cacheService.Cleanup(); - + _logger.LogInformation("Cleaning old database backups"); + _backupService.CleanupBackups(); + } } } \ No newline at end of file