разные правки по беку
This commit is contained in:
@@ -7,7 +7,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence;
|
||||
public class ApprovalRouteDbContext(DbContextOptions<ApprovalRouteDbContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<RequestType> RequestTypes => Set<RequestType>();
|
||||
public DbSet<RequestTypeList> RequestTypeLists => Set<RequestTypeList>();
|
||||
public DbSet<RequestListPartition> RequestListPartitions => Set<RequestListPartition>();
|
||||
public DbSet<TemplateRoute> TemplateRoutes => Set<TemplateRoute>();
|
||||
public DbSet<TemplateRouteStep> TemplateRouteSteps => Set<TemplateRouteStep>();
|
||||
public DbSet<AppSetting> Settings => Set<AppSetting>();
|
||||
@@ -34,13 +34,12 @@ public class ApprovalRouteDbContext(DbContextOptions<ApprovalRouteDbContext> opt
|
||||
e.Property(x => x.Section).HasMaxLength(256).IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RequestTypeList>(e =>
|
||||
modelBuilder.Entity<RequestListPartition>(e =>
|
||||
{
|
||||
e.HasKey(x => x.Id);
|
||||
e.Property(x => x.SiteUrl).HasMaxLength(512).IsRequired();
|
||||
e.Property(x => x.ListId).HasMaxLength(512).IsRequired();
|
||||
e.Property(x => x.Title).HasMaxLength(512);
|
||||
e.HasOne(x => x.RequestType).WithMany(x => x.Lists).HasForeignKey(x => x.RequestTypeId);
|
||||
e.HasOne(x => x.RequestType).WithMany(x => x.ListPartitions).HasForeignKey(x => x.RequestTypeId);
|
||||
// Номер уникален в пределах типа заявок — вторая попытка записать тот же
|
||||
// номер (например, при двойном запуске задачи) упадёт на этом индексе,
|
||||
// а не создаст в реестре дубль.
|
||||
|
||||
+6
-6
@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
namespace Tnsu.ApprovalRoute.Infrastructure.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// Блокировка «по типу заявок идёт создание следующего списка» на строке
|
||||
/// Блокировка «по типу заявок идёт создание следующей партиции списка» на строке
|
||||
/// request_types.
|
||||
///
|
||||
/// Почему сырой SQL, а не обычный EF: через change tracker это было бы
|
||||
@@ -17,7 +17,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence;
|
||||
/// блокировку было видно в самой строке (админке — что провижининг идёт) и чтобы
|
||||
/// она переживала возврат соединения в пул между шагами задачи.
|
||||
/// </summary>
|
||||
public sealed class RequestTypeProvisioningLock(ApprovalRouteDbContext db)
|
||||
public sealed class ListPartitioningLock(ApprovalRouteDbContext db)
|
||||
{
|
||||
/// <summary>
|
||||
/// Попытаться захватить блокировку. true — захватили (и только тогда можно
|
||||
@@ -33,10 +33,10 @@ public sealed class RequestTypeProvisioningLock(ApprovalRouteDbContext db)
|
||||
var affected = await db.Database.ExecuteSqlInterpolatedAsync(
|
||||
$"""
|
||||
UPDATE request_types
|
||||
SET list_provisioning_started_at = now()
|
||||
SET list_partitioning_started_at = now()
|
||||
WHERE id = {requestTypeId}
|
||||
AND (list_provisioning_started_at IS NULL
|
||||
OR list_provisioning_started_at < now() - CAST({staleAfter} AS interval))
|
||||
AND (list_partitioning_started_at IS NULL
|
||||
OR list_partitioning_started_at < now() - CAST({staleAfter} AS interval))
|
||||
""",
|
||||
cancellationToken);
|
||||
|
||||
@@ -46,6 +46,6 @@ public sealed class RequestTypeProvisioningLock(ApprovalRouteDbContext db)
|
||||
/// <summary>Снять блокировку. Идемпотентно: снятая блокировка снимается повторно без ошибки.</summary>
|
||||
public Task ReleaseAsync(int requestTypeId, CancellationToken cancellationToken) =>
|
||||
db.Database.ExecuteSqlInterpolatedAsync(
|
||||
$"UPDATE request_types SET list_provisioning_started_at = NULL WHERE id = {requestTypeId}",
|
||||
$"UPDATE request_types SET list_partitioning_started_at = NULL WHERE id = {requestTypeId}",
|
||||
cancellationToken);
|
||||
}
|
||||
+50
-56
@@ -12,8 +12,8 @@ using Tnsu.ApprovalRoute.Infrastructure.Persistence;
|
||||
namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApprovalRouteDbContext))]
|
||||
[Migration("20260817084927_AddRequestTypeListsRegistry")]
|
||||
partial class AddRequestTypeListsRegistry
|
||||
[Migration("20260817102423_AddListPartitioning")]
|
||||
partial class AddListPartitioning
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@@ -25,6 +25,48 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestListPartition", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<string>("ListId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("list_id");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<int>("RequestTypeId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("request_type_id");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_request_list_partitions");
|
||||
|
||||
b.HasIndex("RequestTypeId", "Number")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_request_list_partitions_request_type_id_number");
|
||||
|
||||
b.ToTable("request_list_partitions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestType", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -43,9 +85,9 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("list_id");
|
||||
|
||||
b.Property<DateTimeOffset?>("ListProvisioningStartedAt")
|
||||
b.Property<DateTimeOffset?>("ListPartitioningStartedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("list_provisioning_started_at");
|
||||
.HasColumnName("list_partitioning_started_at");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
@@ -80,54 +122,6 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("request_types", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestTypeList", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<string>("ListId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("list_id");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<int>("RequestTypeId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("request_type_id");
|
||||
|
||||
b.Property<string>("SiteUrl")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("site_url");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_request_type_lists");
|
||||
|
||||
b.HasIndex("RequestTypeId", "Number")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_request_type_lists_request_type_id_number");
|
||||
|
||||
b.ToTable("request_type_lists", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -267,14 +261,14 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("settings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestTypeList", b =>
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestListPartition", b =>
|
||||
{
|
||||
b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.RequestType", "RequestType")
|
||||
.WithMany("Lists")
|
||||
.WithMany("ListPartitions")
|
||||
.HasForeignKey("RequestTypeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_request_type_lists_request_types_request_type_id");
|
||||
.HasConstraintName("fk_request_list_partitions_request_types_request_type_id");
|
||||
|
||||
b.Navigation("RequestType");
|
||||
});
|
||||
@@ -305,7 +299,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestType", b =>
|
||||
{
|
||||
b.Navigation("Lists");
|
||||
b.Navigation("ListPartitions");
|
||||
|
||||
b.Navigation("Routes");
|
||||
});
|
||||
+9
-10
@@ -7,35 +7,34 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddRequestTypeListsRegistry : Migration
|
||||
public partial class AddListPartitioning : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "list_provisioning_started_at",
|
||||
name: "list_partitioning_started_at",
|
||||
table: "request_types",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "request_type_lists",
|
||||
name: "request_list_partitions",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
request_type_id = table.Column<int>(type: "integer", nullable: false),
|
||||
number = table.Column<int>(type: "integer", nullable: false),
|
||||
site_url = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
|
||||
list_id = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
|
||||
title = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_request_type_lists", x => x.id);
|
||||
table.PrimaryKey("pk_request_list_partitions", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_request_type_lists_request_types_request_type_id",
|
||||
name: "fk_request_list_partitions_request_types_request_type_id",
|
||||
column: x => x.request_type_id,
|
||||
principalTable: "request_types",
|
||||
principalColumn: "id",
|
||||
@@ -43,8 +42,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_request_type_lists_request_type_id_number",
|
||||
table: "request_type_lists",
|
||||
name: "ix_request_list_partitions_request_type_id_number",
|
||||
table: "request_list_partitions",
|
||||
columns: new[] { "request_type_id", "number" },
|
||||
unique: true);
|
||||
}
|
||||
@@ -53,10 +52,10 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "request_type_lists");
|
||||
name: "request_list_partitions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "list_provisioning_started_at",
|
||||
name: "list_partitioning_started_at",
|
||||
table: "request_types");
|
||||
}
|
||||
}
|
||||
+48
-54
@@ -22,6 +22,48 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestListPartition", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<string>("ListId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("list_id");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<int>("RequestTypeId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("request_type_id");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_request_list_partitions");
|
||||
|
||||
b.HasIndex("RequestTypeId", "Number")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_request_list_partitions_request_type_id_number");
|
||||
|
||||
b.ToTable("request_list_partitions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestType", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -40,9 +82,9 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("list_id");
|
||||
|
||||
b.Property<DateTimeOffset?>("ListProvisioningStartedAt")
|
||||
b.Property<DateTimeOffset?>("ListPartitioningStartedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("list_provisioning_started_at");
|
||||
.HasColumnName("list_partitioning_started_at");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
@@ -77,54 +119,6 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("request_types", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestTypeList", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<string>("ListId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("list_id");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<int>("RequestTypeId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("request_type_id");
|
||||
|
||||
b.Property<string>("SiteUrl")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("site_url");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_request_type_lists");
|
||||
|
||||
b.HasIndex("RequestTypeId", "Number")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_request_type_lists_request_type_id_number");
|
||||
|
||||
b.ToTable("request_type_lists", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -264,14 +258,14 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("settings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestTypeList", b =>
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestListPartition", b =>
|
||||
{
|
||||
b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.RequestType", "RequestType")
|
||||
.WithMany("Lists")
|
||||
.WithMany("ListPartitions")
|
||||
.HasForeignKey("RequestTypeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_request_type_lists_request_types_request_type_id");
|
||||
.HasConstraintName("fk_request_list_partitions_request_types_request_type_id");
|
||||
|
||||
b.Navigation("RequestType");
|
||||
});
|
||||
@@ -302,7 +296,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
|
||||
|
||||
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestType", b =>
|
||||
{
|
||||
b.Navigation("Lists");
|
||||
b.Navigation("ListPartitions");
|
||||
|
||||
b.Navigation("Routes");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user