feat(dal): Модели и сервисы для работы с Task

This commit is contained in:
Mikhail Trubnikov
2026-03-17 16:50:49 +10:00
parent 547cb894be
commit 01c0200c6d
14 changed files with 294 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ using PARR.DAL.Extensions;
using PARR.DAL.Models;
using PARR.DAL.Models.Job;
using PARR.DAL.Models.Schedule;
using PARR.DAL.Models.Task;
using PARR.DAL.Models.Unit;
namespace PARR.DAL.Context
@@ -117,6 +118,15 @@ namespace PARR.DAL.Context
#endregion
#region Tasks
public DbSet<PARR.DAL.Models.Task.Task> Tasks { get; set; }
public DbSet<PARR.DAL.Models.Task.TaskStatus> TaskStatus { get; set; }
public DbSet<TaskType> TaskTypes { get; set; }
public DbSet<TaskError> TaskErrors { get; set; }
#endregion
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@@ -555,6 +565,35 @@ namespace PARR.DAL.Context
#endregion
#region TaskType
modelBuilder.Entity<TaskType>(f =>
{
f.HasData(new TaskType[]
{
new() { Code = TaskTypeEnum.Workload, Name = TaskTypeEnum.Workload.ToString(), Description = "Формирование данных для отчетности - Загруженность", MaxRetries = 2 }
}
);
});
#endregion
#region TaskStatus
modelBuilder.Entity<PARR.DAL.Models.Task.TaskStatus>(f =>
{
f.HasData(new PARR.DAL.Models.Task.TaskStatus[]
{
new(){Code=TaskTaskStatusEnum.Wait, Name=TaskTaskStatusEnum.Wait.ToString(), Description="Ожидание"},
new(){Code=TaskTaskStatusEnum.Processing, Name=TaskTaskStatusEnum.Processing.ToString(), Description="В работе"},
new(){Code=TaskTaskStatusEnum.Success, Name=TaskTaskStatusEnum.Success.ToString(), Description="Выполнено успешно"},
new(){Code=TaskTaskStatusEnum.Error, Name=TaskTaskStatusEnum.Error.ToString(), Description="Ошибка"}
});
});
#endregion
}
//protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

View File

@@ -18,5 +18,11 @@
/// Расписание регламентных работ
/// </summary>
public const string Schedule = "schedule";
/// <summary>
/// Управление очередями
/// </summary>
public const string Task = "task";
}
}

View File

@@ -1,5 +1,7 @@
namespace PARR.DAL.Contracts
{
//TODO: Надо это переименовать в RobotTaskStatusEnum
/// <summary>
/// Статус задания на синхронизацию
/// </summary>

View File

@@ -0,0 +1,30 @@
namespace PARR.DAL.Contracts
{
// TODO: Сначала надо переименовать TaskStatusEnum -> RobotTaskStatusEnum, а потом TaskTaskStatusEnum -> TaskStatusEnum
/// <summary>
/// Статус задач Task
/// </summary>
public enum TaskTaskStatusEnum
{
/// <summary>
/// Ожидание
/// </summary>
Wait=10,
/// <summary>
/// В работе
/// </summary>
Processing = 20,
/// <summary>
/// Выполнено успешно
/// </summary>
Success = 30,
/// <summary>
/// Ошибка
/// </summary>
Error = 40
}
}

View File

@@ -0,0 +1,13 @@
namespace PARR.DAL.Contracts
{
/// <summary>
/// Типы заданий
/// </summary>
public enum TaskTypeEnum
{
/// <summary>
/// Загруженность
/// </summary>
Workload = 0,
}
}

View File

@@ -0,0 +1,47 @@
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Context;
using PARR.DAL.Contracts;
using PARR.DAL.Models.Base;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PARR.DAL.Models.Task
{
[Table("Tasks", Schema = DataContextSettings.Task)]
[Comment("Таблица заданий")]
public class Task : IBase
{
[Key]
public Guid Id { get; set; }
public DateTimeOffset DateCreated { get; set; }
public DateTimeOffset? DateModified { get; set; }
public TaskTypeEnum TypeCode { get; set; }
public TaskTaskStatusEnum StatusCode { get; set; }
public string? Payload { get; set; }
/// <summary>
/// Кол-во попыток
/// </summary>
public int RetryCount { get; set; }
/// <summary>
/// Дата завершения (устанавливается или когда Успех или когда Ошибка)
/// </summary>
public DateTimeOffset? ProcessedAt { get; set; }
[ForeignKey(nameof(TypeCode))]
public TaskType? TaskType { get; set; }
[ForeignKey(nameof(StatusCode))]
public TaskStatus? TaskStatus { get; set; }
public ICollection<TaskError> TaskErrors { get; set; } = new HashSet<TaskError>();
}
}

View File

@@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Context;
using PARR.DAL.Models.Base;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PARR.DAL.Models.Task
{
[Table("Errors", Schema = DataContextSettings.Task)]
[Comment("Таблица ошибок заданий")]
public class TaskError : IBase
{
[Key]
public Guid Id { get; set; }
public DateTimeOffset DateCreated { get; set; }
[NotMapped]
public DateTimeOffset? DateModified { get; set; }
public Guid TaskId { get; set; }
public int AttemptNumber { get; set; }
public required string ErrorMessage { get; set; }
public string? StackTrace { get; set; }
[ForeignKey(nameof(TaskId))]
public Task? Task { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Context;
using PARR.DAL.Contracts;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PARR.DAL.Models.Task
{
[Table("Statuses", Schema = DataContextSettings.Task)]
[Comment("Таблица статусов заданий")]
public class TaskStatus
{
[Key]
public TaskTaskStatusEnum Code { get; set; }
public required string Name { get; set; }
public required string Description { get; set; }
public ICollection<Task> Tasks { get; set; } = new HashSet<Task>();
}
}

View File

@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Context;
using PARR.DAL.Contracts;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PARR.DAL.Models.Task
{
[Table("Types", Schema = DataContextSettings.Task)]
[Comment("Таблица типов заданий")]
public class TaskType
{
[Key]
public TaskTypeEnum Code { get; set; }
public required string Name { get; set; }
public required string Description { get; set; }
/// <summary>
/// Максимальное кол-во попыток
/// </summary>
public int MaxRetries { get; set; }
public ICollection<Task> Tasks { get; set; } = new HashSet<Task>();
}
}

View File

@@ -18,10 +18,12 @@ using PARR.DAL.Services.Implementation;
using PARR.DAL.Services.Implementations;
using PARR.DAL.Services.Implementations.Job;
using PARR.DAL.Services.Implementations.Schedule;
using PARR.DAL.Services.Implementations.Task;
using PARR.DAL.Services.Implementations.Unit;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Schedule;
using PARR.DAL.Services.Interfaces.Task;
using PARR.DAL.Services.Interfaces.Unit;
using PARR.DAL.Settings;
using StackExchange.Redis;
@@ -144,6 +146,13 @@ namespace PARR.DAL
#endregion
#region Task
services.AddTransient<ITaskErrorService, TaskErrorService>();
services.AddTransient<ITaskService, TaskService>();
#endregion
//services.AddTransient<INextRunModifierService, NextRunModifierService>();
#region NextRun Services

View File

@@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.DAL.Context;
using PARR.DAL.Models.Task;
using PARR.DAL.Services.Abstracts;
using PARR.DAL.Services.Interfaces.Task;
namespace PARR.DAL.Services.Implementations.Task
{
internal class TaskErrorService : BaseService<TaskError>, ITaskErrorService
{
private readonly DataContext dataContext;
protected override DbSet<TaskError> EntitySet => dataContext.TaskErrors;
protected override DataContext EntitiContext => dataContext;
public TaskErrorService(DataContext dataContext, ILogger<TaskErrorService> logger): base(logger)
{
this.dataContext = dataContext;
}
}
}

View File

@@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.DAL.Context;
using PARR.DAL.Services.Abstracts;
using PARR.DAL.Services.Interfaces.Task;
namespace PARR.DAL.Services.Implementations.Task
{
internal class TaskService : BaseService<PARR.DAL.Models.Task.Task>, ITaskService
{
private readonly DataContext dataContext;
protected override DbSet<Models.Task.Task> EntitySet => dataContext.Tasks;
protected override DataContext EntitiContext => dataContext;
public TaskService(DataContext dataContext, ILogger<TaskService> logger) : base(logger)
{
this.dataContext = dataContext;
}
// метод атомарного взятия в работу
}
}

View File

@@ -0,0 +1,9 @@
using PARR.DAL.Models.Task;
using PARR.DAL.Services.Interfaces.Base;
namespace PARR.DAL.Services.Interfaces.Task
{
public interface ITaskErrorService : IBaseService<TaskError>
{
}
}

View File

@@ -0,0 +1,8 @@
using PARR.DAL.Services.Interfaces.Base;
namespace PARR.DAL.Services.Interfaces.Task
{
public interface ITaskService : IBaseService<PARR.DAL.Models.Task.Task>
{
}
}