From de7a3a3a2df9b28061270f0de76d45be3a5946fa Mon Sep 17 00:00:00 2001 From: claude Date: Thu, 28 May 2026 08:50:19 +0300 Subject: [PATCH] feat(myai-data): cleanup migration removes email.* and ai.* templates; update CLAUDE.md - Add DeleteMigratedTemplates migration: removes all email.* and ai.* rows from myAi.Templates (now owned by emailApi.EmailTemplates and cvMatcher.AiPrompts respectively) - CLAUDE.md: add email-api-data to solution layout; add emailApi schema to database schemas table; add email-api-data EF CLI migration command; note cv-matcher-api no longer runs MyAi migrations Co-Authored-By: Claude Sonnet 4.6 --- ...120000_DeleteMigratedTemplates.Designer.cs | 62 +++++++++++++++++++ .../20260528120000_DeleteMigratedTemplates.cs | 24 +++++++ CLAUDE.md | 16 ++++- 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.Designer.cs create mode 100644 Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.cs diff --git a/Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.Designer.cs b/Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.Designer.cs new file mode 100644 index 0000000..d41e5cf --- /dev/null +++ b/Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.Designer.cs @@ -0,0 +1,62 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyAi.Data; + +#nullable disable + +namespace MyAi.Data.Migrations +{ + [DbContext(typeof(MyAiDbContext))] + [Migration("20260528120000_DeleteMigratedTemplates")] + partial class DeleteMigratedTemplates + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("myAi") + .HasAnnotation("ProductVersion", "10.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("MyAi.Data.Entities.TemplateEntity", b => + { + b.Property("Key") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Language") + .HasMaxLength(8) + .HasColumnType("nvarchar(8)"); + + b.Property("Description") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasDefaultValue(""); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("SYSUTCDATETIME()"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Key", "Language"); + + b.ToTable("Templates", "myAi"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.cs b/Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.cs new file mode 100644 index 0000000..426c592 --- /dev/null +++ b/Apis/myai-data/Migrations/20260528120000_DeleteMigratedTemplates.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyAi.Data.Migrations +{ + /// + public partial class DeleteMigratedTemplates : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("DELETE FROM [myAi].[Templates] WHERE [Key] LIKE 'email.%'"); + migrationBuilder.Sql("DELETE FROM [myAi].[Templates] WHERE [Key] LIKE 'ai.%'"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + // Rows were migrated to emailApi.EmailTemplates and cvMatcher.AiPrompts. + // Re-inserting them here is intentionally omitted. + } + } +} diff --git a/CLAUDE.md b/CLAUDE.md index 6443417..948be91 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -65,16 +65,17 @@ Apis/ api-models/ DTOs and settings for api only. email-api/ Internal SMTP email relay (no public port). All email sending goes here. email-api-models/ Refit client + SendEmailRequest + EmailApiSettings (shared by api and cv-search-job). - cv-matcher-api/ Internal CV match engine (port 8082). Runs CvMatcher + CvSearch + MyAi DB migrations. + cv-matcher-api/ Internal CV match engine (port 8082). Runs CvMatcher + CvSearch DB migrations. cv-matcher-api-models/ DTOs shared between api and cv-matcher-api (incl. JobSearchSettings). rag-api/ Internal RAG/vector-search service (port 8081). rag-api-models/ DTOs shared with rag-api. common/ Cross-service infrastructure primitives (DatabaseSettings, InternalApiSettings, etc.). shared-data/ Abstract BaseEntity base class. No DbContext. - cv-matcher-data/ CvMatcherDbContext + entities + migrations (schema: cvMatcher). + cv-matcher-data/ CvMatcherDbContext + entities + migrations (schema: cvMatcher). Owns AiPrompts table. cv-search-data/ CvSearchDbContext + entities + migrations (schema: cvSearch). + email-api-data/ EmailApiDbContext + entities + migrations (schema: emailApi). Owns EmailTemplates table. rag-data/ RagDbContext + entities + migrations (schema: rag). - myai-data/ MyAiDbContext + entities + migrations (schema: myAi). + myai-data/ MyAiDbContext + entities + migrations (schema: myAi). Keeps only html.* templates. Helpers/ startup-helpers/ Shared Program.cs bootstrap: Serilog, Swagger, .env loading, Azure Key Vault, middleware. common-helpers/ Utility helpers. @@ -110,12 +111,15 @@ Config lives in `docker-compose/.env`. All env vars use `${VAR:-default}` fallba | Schema | Owner DbContext | Migrations project | Startup project | |-------------|----------------------|-----------------------|-----------------------| | `cvMatcher` | `CvMatcherDbContext` | `cv-matcher-data` | `cv-matcher-api` | +| `emailApi` | `EmailApiDbContext` | `email-api-data` | `email-api` | | `rag` | `RagDbContext` | `rag-data` | `rag-api` | | `cvSearch` | `CvSearchDbContext` | `cv-search-data` | `cv-matcher-api` | | `myAi` | `MyAiDbContext` | `myai-data` | `api` | Both `cv-matcher-api` and `cv-search-job` register `CvSearchDbContext` and call `db.Database.Migrate()` on startup (idempotent — safe for both to run). +`api` and `cv-search-job` also register `EmailApiDbContext` (read-only — `email-api` is the sole migration owner). They use it to load email templates via `IEmailTemplateService` (10-min cache, singleton). + ## EF Core migrations ```powershell @@ -125,6 +129,12 @@ dotnet ef migrations add ` --project Apis/cv-matcher-data ` --startup-project Apis/cv-matcher-api +# email-api-data (schema: emailApi) +dotnet ef migrations add ` + --context EmailApiDbContext ` + --project Apis/email-api-data ` + --startup-project Apis/email-api + # rag-data (schema: rag) dotnet ef migrations add ` --context RagDbContext `