using System.CommandLine; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; using GSS2.Core; using GSS2.Core.Hardware; using GSS2.Core.Analysis.AmineContent.Database.Calibration; using GSS2.Core.Analysis.AmineContent.Database.Results; namespace GSS2.Commands; public static class ImageStorageClear { private class ImageStorageClearWorker : BackgroundService { private readonly ILogger _logger; private readonly IHostApplicationLifetime _applicationLifetime; private readonly AmineContentCalibrationContext _context; private readonly ImageStorageService _imageStorage; public ImageStorageClearWorker( ILogger logger, IHostApplicationLifetime applicationLifetime, AmineContentCalibrationContext context, ImageStorageService imageStorage ) { _applicationLifetime = applicationLifetime; _logger = logger; _context = context; _imageStorage = imageStorage; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // Логгируем информацию _logger.LogInformation("Очистка хранилища от неиспользуемых изображений..."); // Получаем все изображения из базы данных var recordsFiles = _context.ImageRecords.Select(r => r.ImagePath); // Получаем все изображения в хранилище var storedFiles = _imageStorage.ListFiles() .Select(Path.GetFileName) .OfType(); // Находим неиспользуемые изображения var unusedFiles = storedFiles.Except(recordsFiles) .ToList() .Order(); // Если неиспользуемых изображений нет, то закрываемся if (unusedFiles is null || unusedFiles.Count() == 0) { _logger.LogInformation("Неиспользуемые изображения не найдены"); _applicationLifetime.StopApplication(); return; } _logger.LogInformation("Найдено неиспользуемых изображений: {}\n\t{}", unusedFiles.Count(), string.Join("\n\t", unusedFiles)); // Пока пользователь не выдал правильное действие или не закрыл приложение while (!stoppingToken.IsCancellationRequested) { // Задаём вопрос _logger.LogInformation("Удалить эти файлы? (Да/Нет) "); // Читаем консоль var input = Console.ReadLine()?.Trim().ToLower(); // Если нет, то выходим if (input == "n" || input == "no" || input == "н" || input == "нет") break; // Если да, то удаляем файлы и выходим if (input == "y" || input == "yes" || input == "д" || input == "да") { foreach (var file in unusedFiles) _imageStorage.Delete(file); break; } } _applicationLifetime.StopApplication(); } } public static readonly RootCommand RootCommand; private static readonly Command Command; static ImageStorageClear() { // Создаём команды, опции, аргументы и пр. RootCommand = new("Очистить хранилище от неиспользуемых изображений"); Command = new("image-storage-clear") { Description = "Очистить хранилище от неиспользуемых изображений" }; // Изменяем описания стандартных опций Helper.TranslateDefaultOptionDescriptions(RootCommand); // Наполняем команды RootCommand.SetAction(CommandAction); Command.SetAction(CommandAction); } /// /// Получить команду как корневую /// public static RootCommand GetCommand() => RootCommand; /// /// Зарегистрировать команду как подкоманду /// /// Команда в которой необходимо зарегистрировать подкоманду public static void RegisterCommand(Command command) => command.Add(Command); private static void CommandAction(ParseResult result) { // Создаём хост var builder = Host.CreateApplicationBuilder(); // Добавляем конфигурацию из appsettings.json builder.Configuration.AddAppSettingsJson(); // Конфигурируем логгер builder.Logging.ConfigureLogging(); // Добавляем сервисы баз данных builder.Services.AddAmineContentCalibrationContext(builder.Configuration); builder.Services.AddAmineContentResultsContext(builder.Configuration); // Добавляем сервисы аппаратной части builder.Services.AddImageStorageService(new DirectoryInfo(builder.Configuration.GetValue("ImageStorage") ?? "images")); // Добавляем рабочий сервис builder.Services.AddHostedService(); // Собираем хост var host = builder.Build(); // Применяем миграции баз данных если их схема данных изменялась using (var scope = host.Services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); context.Database.Migrate(); } using (var scope = host.Services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); context.Database.Migrate(); } // Запускаем хост host.Run(); } }