From 634c907c9fe18e9c07f7d8076eaf43f82e45dc66 Mon Sep 17 00:00:00 2001 From: df123 Date: Wed, 25 Feb 2026 22:41:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=A3=81=E7=9B=98?= =?UTF-8?q?=E7=A9=BA=E9=97=B4=E6=A3=80=E6=9F=A5=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=9B=A0=E7=A9=BA=E9=97=B4=E4=B8=8D=E8=B6=B3?= =?UTF-8?q?=E8=80=8C=E6=9A=82=E5=AD=98=E7=9A=84=E4=B8=8B=E8=BD=BD=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/add-disk-space-check.sql | 2 + .../Rss/RssSubscriptionDto.cs | 2 + .../Background/DiskSpaceCheckWorker.cs | 54 +++++++++++ .../Rss/RssSubscriptionService.cs | 95 +++++++++++++++++++ .../Rss/IRssSubscriptionService.cs | 1 + .../Rss/RssSubscriptionDownload.cs | 2 + 6 files changed, 156 insertions(+) create mode 100644 sql/add-disk-space-check.sql create mode 100644 src/DFApp.Application/Background/DiskSpaceCheckWorker.cs diff --git a/sql/add-disk-space-check.sql b/sql/add-disk-space-check.sql new file mode 100644 index 00000000..6b330d61 --- /dev/null +++ b/sql/add-disk-space-check.sql @@ -0,0 +1,2 @@ +-- 添加磁盘空间暂存字段到订阅下载表 +ALTER TABLE "AppRssSubscriptionDownloads" ADD COLUMN "IsPendingDueToLowDiskSpace" INTEGER NOT NULL DEFAULT 0; diff --git a/src/DFApp.Application.Contracts/Rss/RssSubscriptionDto.cs b/src/DFApp.Application.Contracts/Rss/RssSubscriptionDto.cs index 5ebabce4..07dcf252 100644 --- a/src/DFApp.Application.Contracts/Rss/RssSubscriptionDto.cs +++ b/src/DFApp.Application.Contracts/Rss/RssSubscriptionDto.cs @@ -111,6 +111,8 @@ public class RssSubscriptionDownloadDto : EntityDto public string? DownloadStatusText { get; set; } + public bool IsPendingDueToLowDiskSpace { get; set; } + public string? ErrorMessage { get; set; } public DateTime? DownloadStartTime { get; set; } diff --git a/src/DFApp.Application/Background/DiskSpaceCheckWorker.cs b/src/DFApp.Application/Background/DiskSpaceCheckWorker.cs new file mode 100644 index 00000000..b34aa686 --- /dev/null +++ b/src/DFApp.Application/Background/DiskSpaceCheckWorker.cs @@ -0,0 +1,54 @@ +using DFApp.Rss; +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Quartz; +using Volo.Abp.BackgroundWorkers.Quartz; +using Volo.Abp.DependencyInjection; + +namespace DFApp.Background +{ + /// + /// 磁盘空间检查后台任务,处理因空间不足而暂存的下载 + /// + public class DiskSpaceCheckWorker : QuartzBackgroundWorkerBase, ITransientDependency + { + private readonly IRssSubscriptionService _rssSubscriptionService; + + public DiskSpaceCheckWorker( + IRssSubscriptionService rssSubscriptionService) + { + _rssSubscriptionService = rssSubscriptionService; + + JobDetail = JobBuilder + .Create() + .WithIdentity(nameof(DiskSpaceCheckWorker)) + .Build(); + + Trigger = TriggerBuilder + .Create() + .WithIdentity(nameof(DiskSpaceCheckWorker)) + .WithSimpleSchedule(x => x + .WithIntervalInMinutes(10) + .RepeatForever()) + .Build(); + } + + public override async Task Execute(IJobExecutionContext context) + { + Logger.LogInformation("开始执行磁盘空间检查任务"); + + try + { + await _rssSubscriptionService.ProcessPendingDownloadsAsync(); + + Logger.LogInformation("磁盘空间检查任务完成"); + } + catch (Exception ex) + { + Logger.LogError(ex, "磁盘空间检查任务执行失败"); + } + } + } +} diff --git a/src/DFApp.Application/Rss/RssSubscriptionService.cs b/src/DFApp.Application/Rss/RssSubscriptionService.cs index ed34b9fa..c6e65fe1 100644 --- a/src/DFApp.Application/Rss/RssSubscriptionService.cs +++ b/src/DFApp.Application/Rss/RssSubscriptionService.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; @@ -163,6 +164,9 @@ public async Task> MatchSubscriptionsAsync(RssM return results; } + private const long MinDiskSpaceGB = 2; + private const long MinDiskSpaceBytes = MinDiskSpaceGB * 1024 * 1024 * 1024; + public async Task CreateDownloadTaskAsync(long subscriptionId, long rssMirrorItemId) { var subscription = await _rssSubscriptionRepository.GetAsync(subscriptionId); @@ -178,6 +182,27 @@ public async Task CreateDownloadTaskAsync(long subscriptionId, long rssMirrorIte return; } + var availableSpace = GetAvailableDiskSpace(); + + if (availableSpace < MinDiskSpaceBytes) + { + _logger.LogWarning("磁盘空间不足 {MinGB} GB,暂存订阅 {SubscriptionName} 的下载: {Title}", + MinDiskSpaceGB, subscription.Name, item.Title); + + var pendingRecord = new RssSubscriptionDownload + { + SubscriptionId = subscriptionId, + RssMirrorItemId = rssMirrorItemId, + Aria2Gid = string.Empty, + DownloadStatus = 0, + IsPendingDueToLowDiskSpace = true, + CreationTime = DateTime.Now + }; + + await _rssSubscriptionDownloadRepository.InsertAsync(pendingRecord); + return; + } + var downloadRequest = new AddDownloadRequestDto { Urls = new List { item.Link }, @@ -203,5 +228,75 @@ public async Task CreateDownloadTaskAsync(long subscriptionId, long rssMirrorIte _logger.LogInformation("订阅 {SubscriptionName} 自动下载: {Title} (GID: {Gid})", subscription.Name, item.Title, result.Id); } + + private long GetAvailableDiskSpace() + { + try + { + var currentDirectory = Directory.GetCurrentDirectory(); + var driveInfo = new DriveInfo(Path.GetPathRoot(currentDirectory)!); + return driveInfo.AvailableFreeSpace; + } + catch (Exception ex) + { + _logger.LogError(ex, "获取磁盘空间失败"); + return 0; + } + } + + public async Task ProcessPendingDownloadsAsync() + { + var availableSpace = GetAvailableDiskSpace(); + + if (availableSpace < MinDiskSpaceBytes) + { + _logger.LogInformation("磁盘空间不足 {MinGB} GB,跳过暂存下载处理", MinDiskSpaceGB); + return; + } + + var pendingDownloads = await _rssSubscriptionDownloadRepository.GetListAsync( + d => d.IsPendingDueToLowDiskSpace && d.DownloadStatus == 0); + + if (!pendingDownloads.Any()) + { + return; + } + + _logger.LogInformation("找到 {Count} 个暂存的下载任务", pendingDownloads.Count); + + foreach (var download in pendingDownloads) + { + try + { + var subscription = await _rssSubscriptionRepository.GetAsync(download.SubscriptionId); + var item = await _rssMirrorItemRepository.GetAsync(download.RssMirrorItemId); + + var downloadRequest = new AddDownloadRequestDto + { + Urls = new List { item.Link }, + VideoOnly = subscription.VideoOnly, + EnableKeywordFilter = subscription.EnableKeywordFilter, + SavePath = subscription.SavePath + }; + + var result = await _aria2Service.AddDownloadAsync(downloadRequest); + + download.Aria2Gid = result.Id; + download.DownloadStatus = 1; + download.DownloadStartTime = DateTime.Now; + download.IsPendingDueToLowDiskSpace = false; + + await _rssSubscriptionDownloadRepository.UpdateAsync(download); + + _logger.LogInformation("已处理暂存下载: {Id} (GID: {Gid})", download.Id, result.Id); + } + catch (Exception ex) + { + _logger.LogError(ex, "处理暂存下载失败: {Id}", download.Id); + } + } + + _logger.LogInformation("已处理 {Count} 个暂存下载任务", pendingDownloads.Count); + } } } diff --git a/src/DFApp.Domain/Rss/IRssSubscriptionService.cs b/src/DFApp.Domain/Rss/IRssSubscriptionService.cs index b58949a6..a214630f 100644 --- a/src/DFApp.Domain/Rss/IRssSubscriptionService.cs +++ b/src/DFApp.Domain/Rss/IRssSubscriptionService.cs @@ -8,6 +8,7 @@ public interface IRssSubscriptionService { Task> MatchSubscriptionsAsync(RssMirrorItem item); Task CreateDownloadTaskAsync(long subscriptionId, long rssMirrorItemId); + Task ProcessPendingDownloadsAsync(); } public class RssSubscriptionMatchResult diff --git a/src/DFApp.Domain/Rss/RssSubscriptionDownload.cs b/src/DFApp.Domain/Rss/RssSubscriptionDownload.cs index 93178d46..02863c0d 100644 --- a/src/DFApp.Domain/Rss/RssSubscriptionDownload.cs +++ b/src/DFApp.Domain/Rss/RssSubscriptionDownload.cs @@ -22,6 +22,8 @@ public class RssSubscriptionDownload : Entity, IHasCreationTime public DateTime? DownloadCompleteTime { get; set; } + public bool IsPendingDueToLowDiskSpace { get; set; } + public DateTime CreationTime { get; set; } public Guid? CreatorId { get; set; }