Глобальный рефакторинг пространств имён
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using Pf2e.Scrapper.Helpers;
|
||||
using Pf2e.Scrapper.Processors.Collection;
|
||||
using Pf2e.Scrapper.Processors.Definitions;
|
||||
using Pf2e.Scrapper.Processors.Factory;
|
||||
|
||||
namespace Pf2e.Scrapper.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// Класс, выполняющий обработку коллекции обработчиков.
|
||||
/// </summary>
|
||||
/// <param name="collection">[DI] <inheritdoc cref="ProcessorCollection"/></param>
|
||||
/// <param name="progress">[DI] <inheritdoc cref="ProcessProgress"/></param>
|
||||
/// <param name="settings">[DI] <inheritdoc cref="ApplicationSettings"/></param>
|
||||
internal sealed class ProcessorExecutor(
|
||||
ProcessorCollection collection,
|
||||
ProcessProgress progress,
|
||||
ApplicationSettings settings
|
||||
)
|
||||
{
|
||||
/// <inheritdoc cref="ProcessorCollection"/>
|
||||
public ProcessorCollection Collection { get; } = collection;
|
||||
|
||||
/// <inheritdoc cref="ProcessProgress"/>
|
||||
public ProcessProgress Progress { get; } = progress;
|
||||
|
||||
/// <inheritdoc cref="ApplicationSettings"/>
|
||||
public ApplicationSettings Settings { get; } = settings;
|
||||
|
||||
/// <summary>
|
||||
/// Запускает обработку коллекции обработчиков.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
Collection.SortItems();
|
||||
|
||||
Progress.Processors.Reset(Collection.Items.Count);
|
||||
|
||||
StartItem();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Текущий индекс обрабатываемого элемента в коллекции.
|
||||
/// </summary>
|
||||
private int _currentIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Текущая фабрика процессоров, которая используется для обработки.
|
||||
/// </summary>
|
||||
private AbstractProcessorFactory CurrentFactory { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Инициирует обработку текущего элемента в коллекции.
|
||||
/// </summary>
|
||||
/// <remarks>Этот метод извлекает текущий элемент из коллекции, подготавливает связанную
|
||||
/// фабрику и запускает фоновый обработчик для обработки задач элемента. Обработка
|
||||
/// выполняется параллельно, если конфигурация элемента это позволяет, со степенью
|
||||
/// параллелизма, определяемой настройками приложения. После завершения обработки метод
|
||||
/// переходит к следующему шагу рабочего процесса.</remarks>
|
||||
private void StartItem()
|
||||
{
|
||||
ProcessorRecord item = Collection.Items[_currentIndex];
|
||||
|
||||
Progress.Processors.Start(item.Description);
|
||||
Progress.Progress(Progress.Processors.ToString());
|
||||
|
||||
BackgroundWorker worker = new();
|
||||
|
||||
CurrentFactory = item.Factory;
|
||||
CurrentFactory.Prepare();
|
||||
|
||||
worker.DoWork += (_, _) =>
|
||||
{
|
||||
Parallel.ForEach(
|
||||
IterateProcessors(),
|
||||
new() { MaxDegreeOfParallelism = item.Parallel ? Settings.MaxThreads : 1 },
|
||||
RunProcessor
|
||||
);
|
||||
};
|
||||
|
||||
worker.RunWorkerCompleted += (_, _) => Continue();
|
||||
|
||||
worker.RunWorkerAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запускает указанный процессор для выполнения операций обработки и сохранения.
|
||||
/// </summary>
|
||||
/// <remarks>Если процессор выдает <see cref="SkipItemException"/>, сообщение об исключении
|
||||
/// регистрируется как информационный прогресс. Если выдается <see cref="SilentSkipItemException"/>,
|
||||
/// оно молча игнорируется.</remarks>
|
||||
/// <param name="processor">Экземпляр процессора, выполняющий операции обработки и сохранения.</param>
|
||||
/// <param name="state">Экземпляр <see cref="ParallelLoopState"/>, который можно использовать для управления выполнением
|
||||
/// параллельного цикла.</param>
|
||||
/// <param name="arg3">Длинное значение, представляющее текущий индекс итерации или связанные данные для процессора.</param>
|
||||
private void RunProcessor(IProcessor processor, ParallelLoopState state, long arg3)
|
||||
{
|
||||
try
|
||||
{
|
||||
processor.Process();
|
||||
processor.Save();
|
||||
}
|
||||
catch (SkipItemException exception)
|
||||
{
|
||||
Progress.Information(exception.Message);
|
||||
}
|
||||
catch (SilentSkipItemException)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переходит к обработке следующего элемента в коллекции или завершает процесс, если все элементы были обработаны.
|
||||
/// </summary>
|
||||
/// <remarks>Этот метод увеличивает текущий индекс и определяет, начинать ли обработку следующего элемента или завершить
|
||||
/// процесс. Если текущий индекс превышает количество элементов в коллекции, процесс помечается как завершенный.</remarks>
|
||||
private void Continue()
|
||||
{
|
||||
Progress.Processors.End();
|
||||
_currentIndex++;
|
||||
|
||||
if (_currentIndex < Collection.Items.Count)
|
||||
{
|
||||
StartItem();
|
||||
}
|
||||
else
|
||||
{
|
||||
Progress.Processors.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполняет итерацию по всем процессорам, предоставленным текущей фабрикой.
|
||||
/// </summary>
|
||||
/// <remarks>Этот метод выдает каждый процессор последовательно, позволяя вызывающему
|
||||
/// обрабатывать их по одному за раз. Отслеживание прогресса обновляется для каждого
|
||||
/// процессора во время итерации.</remarks>
|
||||
/// <returns>Перечисляемая коллекция экземпляров <see cref="IProcessor" />,
|
||||
/// представляющая процессоры, доступные в текущей фабрике.</returns>
|
||||
private IEnumerable<IProcessor> IterateProcessors()
|
||||
{
|
||||
Progress.Local.Reset(CurrentFactory.Count());
|
||||
|
||||
foreach ((string title, IProcessor processor) in CurrentFactory.GetEnumerator())
|
||||
{
|
||||
Progress.Local.Start(title);
|
||||
|
||||
yield return processor;
|
||||
|
||||
Progress.Local.End();
|
||||
}
|
||||
|
||||
Progress.Local.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Исключение, показывающее, что обработка сущности пропускается как устаревшая.
|
||||
/// </summary>
|
||||
/// <param name="name">Название сущности.</param>
|
||||
public class LegacyItemException(string name) : SkipItemException(name, "Устаревший элемент") { }
|
||||
|
||||
/// <summary>
|
||||
/// Исключение, показывающее, что обработка сущности пропускается.
|
||||
/// </summary>
|
||||
/// <param name="name">Название сущности.</param>
|
||||
/// <param name="reason">Причина пропуска.</param>
|
||||
public class SkipItemException(string name, string reason)
|
||||
: Exception($"Пропускаю элемент '{name}', указана причина: {reason}.") { }
|
||||
|
||||
/// <summary>
|
||||
/// Исключение, показывающее, что обработка сущности пропускается без вывода сообщения.
|
||||
/// </summary>
|
||||
public class SilentSkipItemException : Exception { }
|
||||
Reference in New Issue
Block a user