Skip to content

vl336/marketmate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MarketMate

Документация

Полезные ссылки


Архитектура

Проект построен на чистой архитектуре с использованием .NET 10 и .NET Aspire для оркестрации сервисов.

Структура решения

MarketMate/
├── MarketMate.AppHost                  # Aspire — оркестрация всех сервисов
├── MarketMate.ServiceDefaults          # Общие настройки: телеметрия, хелсчеки, resilience
│
├── MarketMate.Domain                   # Доменные модели (без зависимостей)
├── MarketMate.Application              # Интерфейсы сервисов и репозиториев, бизнес-логика
│
├── MarketMate.Infrastructure.Postgre   # EF Core + PostgreSQL: DbContext, репозитории, миграции
├── MarketMate.Infrastructure.Kafka     # Реализация IEventBus через Kafka
├── MarketMate.Infrastructure.DependencyInjection  # Точка сборки всех зависимостей
│
├── MarketMate.Llm                      # Интеграция с LLM (Yandex через SemanticKernel)
│
├── MarketMate.Api                      # HTTP API (ASP.NET Core)
├── MarketMate.Worker                   # Фоновый сервис
└── MarktetMate.Talker                  # Отдельный сервис

Слои и правила зависимостей

Api / Worker
        ↓
Infrastructure.DependencyInjection  ←  Infrastructure.Postgre
        ↓                           ←  Infrastructure.Kafka
   Application                      ←  Llm
        ↓
      Domain
  • Domain — чистые модели, никаких зависимостей
  • Application — только интерфейсы (IUnitOfWorkFactory, IEventBus, ILlmService, сервисы). Зависит только от Domain
  • Infrastructure — реализации интерфейсов из Application. Знает про EF, Kafka, LLM
  • DependencyInjection — единственное место где всё собирается вместе, регистрирует все зависимости
  • Api/Worker — вызывают builder.AddInfrastructure() и получают всё готовое

Принципы чистой архитектуры в проекте

1. Направление зависимостей — всегда внутрь

Внешние слои знают о внутренних, но не наоборот. Domain не знает про EF, API, Kafka — ничего. Application знает только про Domain. Инфраструктура знает про Application и реализует его интерфейсы.

Если хочется сделать using MarketMate.Infrastructure.* в Domain или Application — это красный флаг, что-то идёт не так.

2. Application оперирует интерфейсами, не реализациями

Application никогда не создаёт new ChatMessageRepository() или new KafkaEventBus(). Всё приходит через DI. Это позволяет легко подменить реализацию — например, заменить Kafka на RabbitMQ без изменений в бизнес-логике.

3. Контроллер — тонкая обёртка над Application

Контроллер не содержит бизнес-логики. Его единственная задача:

  • принять HTTP запрос
  • передать данные в сервис из Application
  • вернуть результат
// Правильно — контроллер делегирует сервису
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateChatMessageRequest request, CancellationToken ct)
{
    var message = await chatMessageService.CreateAsync(request.Content, request.Role, ct);
    return Ok(message);
}

// Неправильно — логика в контроллере
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateChatMessageRequest request)
{
    var message = new ChatMessage { Id = Guid.NewGuid(), ... }; // не сюда
    await dbContext.SaveChangesAsync();                          // не сюда
    return Ok(message);
}

4. Инфраструктура реализует, Application объявляет

Все контракты объявляются в Application (IUnitOfWorkFactory, IEventBus, ILlmService, репозитории). Инфраструктурные проекты их реализуют. Такой подход называется Dependency Inversion — зависимость от абстракции, а не от конкретики.

5. DependencyInjection — единственное место где всё знает про всё

Только Infrastructure.DependencyInjection знает одновременно про Application и все инфраструктурные проекты. Он связывает интерфейсы с реализациями. Больше нигде в проекте не должно быть new ConcreteImplementation() для сервисов.


Ключевые паттерны

UnitOfWork + репозитории

Все операции с БД идут через IUnitOfWorkFactory. Фабрика сама управляет транзакцией — открывает, коммитит или роллбачит:

await uowFactory.ExecuteAsync(async uow =>
{
    await uow.ChatMessages.AddAsync(message);
});

var message = await uowFactory.ExecuteAsync(async uow =>
    await uow.ChatMessages.GetByIdAsync(id));

Каждый вызов ExecuteAsync — отдельный DbContext и транзакция.

Event Bus

Публикация событий через IEventBus. Реализация — Kafka (заглушка, готова к реализации):

await eventBus.PublishAsync(new SomeEvent(...));

LLM интеграция

В Application доступен ILlmService. В инфраструктуре он адаптирован из IChatService (Yandex через SemanticKernel).

Проект работает в broker-only режиме. Для команды добавлен шаблон .env.example в корне репозитория.

Минимум для запуска LLM:

YANDEX_IAM_BROKER_BASE_URL=https://functions.yandexcloud.net/<your-broker-function-id>
YANDEX_IAM_BROKER_API_KEY=<your-broker-api-key>

Для Windows можно задать значения через скрипт:

powershell -ExecutionPolicy Bypass -File .\ops\set-yandex-broker-env.ps1 -BaseUrl "https://functions.yandexcloud.net/<your-broker-function-id>" -ApiKey "<your-broker-api-key>"

Миграции

Миграции лежат в MarketMate.Infrastructure.Postgre/Migrations. Применяются автоматически при старте API и Worker.

Создать новую миграцию:

cd MarketMate.Infrastructure.Postgre
dotnet ef migrations add <MigrationName>

Запуск

Для запуска нужен Docker (Aspire поднимает PostgreSQL в контейнере).

Aspire Dashboard откроется на http://localhost:15888 — там видны все сервисы, логи и трейсы.

Worker и Talker по умолчанию запускаются вручную через Dashboard (WithExplicitStart).

PostgreSQL контейнер персистентный — не пересоздаётся при каждом запуске (ContainerLifetime.Persistent).

Деплой через Docker Compose

Актуальный деплой лежит в MarketMate/deploy/docker-compose.yml.

Быстрый запуск:

Set-Location "C:\Users\Vladislav\Desktop\marketmate\MarketMate\deploy"
powershell -ExecutionPolicy Bypass -File .\start.ps1

Ручной запуск:

Set-Location "C:\Users\Vladislav\Desktop\marketmate\MarketMate\deploy"
Copy-Item .env.example .env
# заполнить .env

docker compose up -d --build

Остановка:

Set-Location "C:\Users\Vladislav\Desktop\marketmate\MarketMate\deploy"
docker compose down

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors