refactor: restructure solution into -models/-data/-api project taxonomy
Phases 1-10 of the planned refactoring:
Phase 1: rename shared-models -> common
- namespace Shared.Models -> Common throughout
- remove stale AspNetCore.Http.Features 5.0 reference
Phase 2: create shared-data with abstract BaseEntity
- BaseEntity: required string Id { get; init; } + DateTime CreatedAt { get; init; }
Phase 3: rename myai-models -> myai-data
- namespace MyAi.Models -> MyAi.Data
- MigrationsAssembly("myai-data")
Phase 4: rename cv-search-models -> cv-search-data
- namespace CvSearch.Models -> CvSearch.Data
- move JobSearchSettings to cv-matcher-api-models
- JobSearch*Entity now inherits BaseEntity
Phase 5: extract rag-data from rag-api
- new project: Apis/rag-data with RagDbContext + entities + migrations
- RagDocumentEntity inherits BaseEntity; cache entities use CacheKey PK
- fix duplicate AddHttpClient<RagAiClient>/AddScoped registrations in rag-api
- MigrationsAssembly("rag-data")
Phase 6: extract cv-matcher-data from cv-matcher-api
- new project: Apis/cv-matcher-data with CvMatcherDbContext + entities + migrations
- CvMatchResultEntity inherits BaseEntity; CvMatcherChatCacheEntity uses CacheKey PK
- MigrationsAssembly("cv-matcher-data")
Phase 7: create empty cv-cleanup-job-models and cv-search-job-models
Phase 8: update all 5 Dockerfiles for renamed/new projects
Phase 9: reorganise .sln virtual folders (Apis/Jobs/Models/Data/Helpers)
- update root CLAUDE.md with new project taxonomy and migration commands
- update cv-matcher-api/CLAUDE.md and cv-search-job/CLAUDE.md
Phase 10: add Directory.Packages.props for centralised NuGet versions
- remove Version= from all PackageReference elements in active .csproj files
No database changes. No runtime behaviour changes.
All MigrationId strings in __EFMigrationsHistory are unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,29 +39,55 @@ This applies to both the staging and production repos as appropriate.
|
||||
- Docker Compose for local and production deployment
|
||||
- Watchtower for automatic container updates in production
|
||||
|
||||
## Project taxonomy
|
||||
|
||||
| Category | Naming | Contains | EF dependency |
|
||||
|----------|--------|----------|---------------|
|
||||
| Executable | `{name}-api`, `{name}-job` | Controllers, Services, Program.cs | Via `ProjectReference` to a `-data` project |
|
||||
| Domain contracts | `{name}-models`, `{name}-api-models`, `{name}-job-models` | DTOs, Refit interfaces, domain-specific Settings | No |
|
||||
| Data layer | `{name}-data` | DbContext, EF entities, Migrations | Yes |
|
||||
| Common contracts | `common` (no suffix) | Infrastructure/technical primitives — no domain ownership | No |
|
||||
| Common base entities | `shared-data` | Abstract `BaseEntity` class (Id + CreatedAt). No DbContext. | No |
|
||||
|
||||
### The `common` project rule
|
||||
|
||||
`common` holds **only infrastructure/technical primitives** with no specific service domain ownership: `DatabaseSettings`, `InternalApiSettings`, `ErrorResponse`, `RateLimitingSettings`, `UploadFileRequest`, AI provider settings, etc. **Never put a business-domain type in `common`** — domain types belong in the owning service's `-models` project.
|
||||
|
||||
### Where migrations live
|
||||
|
||||
**Migrations always live in the `-data` project**, never in an API or Job project. EF CLI split: `--project` = `-data` project (owns the schema); `--startup-project` = whichever API supplies the DB connection string.
|
||||
|
||||
## Solution layout
|
||||
|
||||
```
|
||||
Apis/
|
||||
api/ Public-facing proxy API (port 8080). Handles CORS, rate limiting, captcha, email.
|
||||
api-models/ DTOs and settings shared by api only.
|
||||
cv-matcher-api/ Internal CV match engine (port 8082). Owns cvMatcher + cvSearch DB schemas.
|
||||
cv-matcher-api-models/ DTOs shared between api and cv-matcher-api.
|
||||
cv-search-models/ EF entities + DbContext for cvSearch schema. Shared by cv-matcher-api and cv-search-job.
|
||||
rag-api/ Internal RAG/vector-search service (port 8081). Owns rag DB schema.
|
||||
api-models/ DTOs and settings for api only.
|
||||
cv-matcher-api/ Internal CV match engine (port 8082). Runs CvMatcher + CvSearch + MyAi 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.
|
||||
shared-models/ Cross-service shared models (DatabaseSettings, etc.).
|
||||
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-search-data/ CvSearchDbContext + entities + migrations (schema: cvSearch).
|
||||
rag-data/ RagDbContext + entities + migrations (schema: rag).
|
||||
myai-data/ MyAiDbContext + entities + migrations (schema: myAi).
|
||||
Helpers/
|
||||
startup-helpers/ Shared Program.cs bootstrap: Serilog, Swagger, .env loading, Azure Key Vault, middleware.
|
||||
common-helpers/ Utility helpers.
|
||||
Jobs/
|
||||
job-scheduler/ IJobTask + JobSchedulerHostedService — the reusable scheduled-job engine.
|
||||
cv-cleanup-job/ Worker: deletes old CVs from file storage. Runs hourly.
|
||||
cv-cleanup-job-models/ Job-specific models for cv-cleanup-job (proactive; currently empty).
|
||||
cv-search-job/ Worker: picks up pending job search sessions, scrapes providers, emails results.
|
||||
web/ Razor Pages / Blazor front-end (port 5000).
|
||||
cv-search-job-models/ Job-specific models for cv-search-job (proactive; currently empty).
|
||||
web/ Razor Pages / Blazor front-end (port 5140).
|
||||
docker-compose/ docker-compose.yml + .env file.
|
||||
```
|
||||
|
||||
Virtual solution folders in `.sln`: `Apis` (executables + web), `Models` (DTOs/contracts), `Data` (data layers), `Jobs`, `Helpers`.
|
||||
|
||||
## Build & restore
|
||||
|
||||
```powershell
|
||||
@@ -79,27 +105,41 @@ Config lives in `docker-compose/.env`. All env vars use `${VAR:-default}` fallba
|
||||
|
||||
## Database schemas
|
||||
|
||||
| Schema | Owner DbContext | Migrations assembly |
|
||||
|-------------|----------------------|-----------------------|
|
||||
| `cvMatcher` | `CvMatcherDbContext` | `cv-matcher-api` |
|
||||
| `rag` | `RagDbContext` | `rag-api` |
|
||||
| `cvSearch` | `CvSearchDbContext` | `cv-search-models` |
|
||||
| Schema | Owner DbContext | Migrations project | Startup project |
|
||||
|-------------|----------------------|-----------------------|-----------------------|
|
||||
| `cvMatcher` | `CvMatcherDbContext` | `cv-matcher-data` | `cv-matcher-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).
|
||||
|
||||
## EF Core migrations
|
||||
|
||||
```powershell
|
||||
# Add a migration to cv-search-models
|
||||
dotnet ef migrations add <MigrationName> \
|
||||
--context CvSearchDbContext \
|
||||
--project Apis/cv-search-models \
|
||||
# cv-matcher-data (schema: cvMatcher)
|
||||
dotnet ef migrations add <MigrationName> `
|
||||
--context CvMatcherDbContext `
|
||||
--project Apis/cv-matcher-data `
|
||||
--startup-project Apis/cv-matcher-api
|
||||
|
||||
# Add a migration to cv-matcher-api
|
||||
dotnet ef migrations add <MigrationName> \
|
||||
--context CvMatcherDbContext \
|
||||
--project Apis/cv-matcher-api
|
||||
# rag-data (schema: rag)
|
||||
dotnet ef migrations add <MigrationName> `
|
||||
--context RagDbContext `
|
||||
--project Apis/rag-data `
|
||||
--startup-project Apis/rag-api
|
||||
|
||||
# cv-search-data (schema: cvSearch)
|
||||
dotnet ef migrations add <MigrationName> `
|
||||
--context CvSearchDbContext `
|
||||
--project Apis/cv-search-data `
|
||||
--startup-project Apis/cv-matcher-api
|
||||
|
||||
# myai-data (schema: myAi)
|
||||
dotnet ef migrations add <MigrationName> `
|
||||
--context MyAiDbContext `
|
||||
--project Apis/myai-data `
|
||||
--startup-project Apis/api
|
||||
```
|
||||
|
||||
EF tools version warning ("older than runtime") is expected and harmless. The `HostAbortedException` output during migration scaffolding is normal — EF starts the host to discover DbContext then aborts it.
|
||||
|
||||
Reference in New Issue
Block a user