88 lines
2.9 KiB
C#
88 lines
2.9 KiB
C#
|
|
using ControlCenter.Api.Entities;
|
|||
|
|
using Microsoft.EntityFrameworkCore;
|
|||
|
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|||
|
|
|
|||
|
|
namespace ControlCenter.Api.Configurations;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// EF Core entity type configuration for the agents table.
|
|||
|
|
/// Enforces snake_case naming, required fields, and index design.
|
|||
|
|
/// </summary>
|
|||
|
|
public class AgentConfiguration : IEntityTypeConfiguration<Agent>
|
|||
|
|
{
|
|||
|
|
public void Configure(EntityTypeBuilder<Agent> builder)
|
|||
|
|
{
|
|||
|
|
// Table name — snake_case
|
|||
|
|
builder.ToTable("agents");
|
|||
|
|
|
|||
|
|
// Primary key
|
|||
|
|
builder.HasKey(a => a.Id);
|
|||
|
|
builder.Property(a => a.Id)
|
|||
|
|
.HasColumnName("id")
|
|||
|
|
.ValueGeneratedOnAdd();
|
|||
|
|
|
|||
|
|
// Status — stored as PostgreSQL enum via Npgsql
|
|||
|
|
builder.Property(a => a.Status)
|
|||
|
|
.HasColumnName("status")
|
|||
|
|
.HasColumnType("agent_status")
|
|||
|
|
.IsRequired();
|
|||
|
|
|
|||
|
|
// Task — nullable text
|
|||
|
|
builder.Property(a => a.Task)
|
|||
|
|
.HasColumnName("task")
|
|||
|
|
.HasColumnType("text");
|
|||
|
|
|
|||
|
|
// Progress — nullable integer (0–100)
|
|||
|
|
builder.Property(a => a.Progress)
|
|||
|
|
.HasColumnName("progress");
|
|||
|
|
|
|||
|
|
// Session key — required, not null
|
|||
|
|
builder.Property(a => a.SessionKey)
|
|||
|
|
.HasColumnName("session_key")
|
|||
|
|
.HasColumnType("text")
|
|||
|
|
.IsRequired();
|
|||
|
|
|
|||
|
|
// Channel — required, not null
|
|||
|
|
builder.Property(a => a.Channel)
|
|||
|
|
.HasColumnName("channel")
|
|||
|
|
.HasColumnType("text")
|
|||
|
|
.IsRequired();
|
|||
|
|
|
|||
|
|
// Last activity — required, defaults to now()
|
|||
|
|
builder.Property(a => a.LastActivity)
|
|||
|
|
.HasColumnName("last_activity")
|
|||
|
|
.HasColumnType("timestamptz")
|
|||
|
|
.IsRequired();
|
|||
|
|
|
|||
|
|
// Created at — auto-set on insert
|
|||
|
|
builder.Property(a => a.CreatedAt)
|
|||
|
|
.HasColumnName("created_at")
|
|||
|
|
.HasColumnType("timestamptz")
|
|||
|
|
.IsRequired()
|
|||
|
|
.HasDefaultValueSql("now()");
|
|||
|
|
|
|||
|
|
// Updated at — auto-set on insert and update
|
|||
|
|
builder.Property(a => a.UpdatedAt)
|
|||
|
|
.HasColumnName("updated_at")
|
|||
|
|
.HasColumnType("timestamptz")
|
|||
|
|
.IsRequired()
|
|||
|
|
.HasDefaultValueSql("now()");
|
|||
|
|
|
|||
|
|
// Indexes
|
|||
|
|
// Sessions are looked up by session_key frequently
|
|||
|
|
builder.HasIndex(a => a.SessionKey)
|
|||
|
|
.HasDatabaseName("ix_agents_session_key")
|
|||
|
|
.IsUnique();
|
|||
|
|
|
|||
|
|
// Agents are filtered by channel for channel-specific queries
|
|||
|
|
builder.HasIndex(a => a.Channel)
|
|||
|
|
.HasDatabaseName("ix_agents_channel");
|
|||
|
|
|
|||
|
|
// Agents are filtered by status for fleet health monitoring
|
|||
|
|
builder.HasIndex(a => a.Status)
|
|||
|
|
.HasDatabaseName("ix_agents_status");
|
|||
|
|
|
|||
|
|
// Check constraint: progress must be 0–100 if present
|
|||
|
|
builder.ToTable(t => t.HasCheckConstraint("ck_agents_progress_range", "progress IS NULL OR (progress >= 0 AND progress <= 100)"));
|
|||
|
|
}
|
|||
|
|
}
|