[feat] update readme.md
This commit is contained in:
parent
c5b6a84a4b
commit
3293bccc5b
5 changed files with 273 additions and 60 deletions
315
README.md
315
README.md
|
|
@ -1,36 +1,268 @@
|
|||
Это шаблон Python-сервиса на чистой архитектуре с заменяемым web-слоем, типизированным конфигом, явным dependency wiring и observability через порты.
|
||||
# master-service
|
||||
|
||||
## Что это за проект
|
||||
`master-service` — это control-plane сервис для sandbox-контейнеров с AI-агентом.
|
||||
Он поднимает и переиспользует sandbox на чат, подключает рабочие volume, восстанавливает state после рестарта и отдает наружу минимальный HTTP API под `/api/v1`.
|
||||
|
||||
- Небольшой референсный сервис со слоями `domain/`, `usecase/`, `repository/` и `adapter/`
|
||||
- Шаблон для сервисов на FastAPI, где FastAPI остается только во внешнем HTTP adapter
|
||||
- Проект, где конфиг собирается из `config/app.yaml`, `.env` и env vars в одно дерево dataclass-конфигов
|
||||
- Проект, где repository и usecase создаются один раз на старте приложения в composition root
|
||||
- Проект, где логи, метрики и трейсы скрыты за интерфейсами и могут работать через `stdout`, файл или OpenTelemetry runtime
|
||||
Важно: в локальном `config/app.yaml` исторически еще стоят template-имена `web-python-skelet`.
|
||||
Если хочешь, чтобы `/health` и OTel service name локально тоже показывали `master-service`, переопредели:
|
||||
- `APP_NAME=master-service`
|
||||
- `APP_OTEL_SERVICE_NAME=master-service`
|
||||
|
||||
## Основные идеи
|
||||
Сервис реализован на Python с Clean Architecture:
|
||||
- `domain/` — сущности и доменные ошибки
|
||||
- `usecase/` — сценарии приложения и порты
|
||||
- `repository/` — реализации repository
|
||||
- `adapter/` — HTTP, config, DI, Docker runtime и observability
|
||||
|
||||
- Clean Architecture и границы SOLID
|
||||
- Направление зависимостей только внутрь
|
||||
- Тонкие adapter-слои и явная сборка зависимостей
|
||||
- Заменяемый HTTP-слой
|
||||
- Observability без протекания OpenTelemetry во внутренние слои
|
||||
## Что умеет сейчас
|
||||
|
||||
Текущий sandbox MVP покрывает:
|
||||
- `GET /api/v1/health`
|
||||
- `POST /api/v1/create` с `chat_id: UUID`
|
||||
- одну активную sandbox на чат
|
||||
- reuse активной sandbox до истечения TTL
|
||||
- cleanup просроченных sandbox в фоне
|
||||
- startup reconciliation по Docker labels после рестарта сервиса
|
||||
- chat mount `rw`, dependencies mount `ro`, lambda-tools mount `ro`
|
||||
- логи, метрики и трейсы через порты `Logger`, `Metrics`, `Tracer`
|
||||
|
||||
Пока вне scope:
|
||||
- auth и access control
|
||||
- p2p/WebSocket lease
|
||||
- workspace/chat CRUD API
|
||||
- central DB, artifacts, S3, quota и retention policy
|
||||
|
||||
## Как устроен проект
|
||||
|
||||
- FastAPI живет только во внешнем adapter слое
|
||||
- Docker живет только во внешнем adapter слое
|
||||
- конфиг собирается из `config/app.yaml`, `.env` и env vars в один dataclass tree
|
||||
- repository и usecase создаются один раз на старте в `adapter/di/container.py`
|
||||
- observability не протекает во внутренние слои через OpenTelemetry SDK
|
||||
|
||||
## Структура
|
||||
|
||||
- `domain/` — core model и domain errors
|
||||
- `usecase/` — use cases и interfaces
|
||||
- `repository/` — in-memory и другие repository implementations
|
||||
- `adapter/config/` — typed config models и loader
|
||||
- `adapter/docker/` — Docker sandbox runtime
|
||||
- `adapter/observability/` — logger/metrics/tracer runtime factory
|
||||
- `adapter/otel/` — OpenTelemetry adapters
|
||||
- `adapter/di/` — composition root
|
||||
- `adapter/http/fastapi/` — app, middleware, schemas, routers
|
||||
- `adapter/sandbox/` — sandbox reconciliation logic
|
||||
- `config/` — YAML config files
|
||||
- `docs/` — ADR и проектные гайды
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### Требования
|
||||
|
||||
- Python 3.13
|
||||
- `uv`
|
||||
- локальный Docker daemon
|
||||
- секреты `APP_API_TOKEN` и `APP_SIGNING_KEY`
|
||||
|
||||
### Установка
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
### Локальный запуск
|
||||
|
||||
```bash
|
||||
APP_API_TOKEN=local-api-token APP_SIGNING_KEY=local-signing-key make run
|
||||
```
|
||||
|
||||
Приложение стартует на `http://0.0.0.0:8123` и публикует versioned API под `/api/v1`.
|
||||
Это поднимет сам API, но для успешного `POST /api/v1/create` локально нужен еще рабочий sandbox runtime:
|
||||
|
||||
- Docker daemon должен быть доступен по `docker.base_url`
|
||||
- образ `sandbox.image` должен существовать локально
|
||||
- директории `sandbox.dependencies_host_path` и `sandbox.lambda_tools_host_path` должны существовать
|
||||
|
||||
В дефолтном `config/app.yaml` это значит:
|
||||
|
||||
```bash
|
||||
mkdir -p var/sandbox/dependencies var/sandbox/lambda-tools
|
||||
docker image inspect ai-agent:latest >/dev/null
|
||||
```
|
||||
|
||||
Если у тебя нет готового `ai-agent:latest`, проще начать с Docker Compose smoke path ниже.
|
||||
|
||||
После старта сервис доступен на:
|
||||
- `http://127.0.0.1:8123/api/v1/health`
|
||||
|
||||
Проверка health:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8123/api/v1/health
|
||||
```
|
||||
|
||||
Создание или reuse sandbox:
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8123/api/v1/create \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"chat_id":"11111111-1111-1111-1111-111111111111"}'
|
||||
```
|
||||
|
||||
Пример ответа:
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "3701cfe3-e05e-48af-8385-442dcd954ca2",
|
||||
"chat_id": "11111111-1111-1111-1111-111111111111",
|
||||
"container_id": "64d839c6007de9396ee08ad4af4a22a59a6410ec5f4892a9277a87eb49c3ff5d",
|
||||
"status": "running",
|
||||
"expires_at": "2026-04-02T21:11:38.292893Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Запуск через Docker Compose
|
||||
|
||||
Для локального smoke-run есть `docker-compose.yml`.
|
||||
Он поднимает:
|
||||
- `app`
|
||||
- `docker-engine` в режиме Docker-in-Docker
|
||||
- `otel-collector`
|
||||
|
||||
При этом `app` получает compose-specific config из:
|
||||
- `config/docker-compose.yml`
|
||||
|
||||
Запуск:
|
||||
|
||||
```bash
|
||||
make compose-up
|
||||
```
|
||||
|
||||
Проверка:
|
||||
|
||||
```bash
|
||||
make compose-ps
|
||||
make compose-logs
|
||||
```
|
||||
|
||||
Остановка:
|
||||
|
||||
```bash
|
||||
make compose-down
|
||||
```
|
||||
|
||||
Важно:
|
||||
- в `config/docker-compose.yml` сейчас для smoke-проверки стоит `sandbox.image: nginx:1.27-alpine`
|
||||
- для реального agent runtime замени `sandbox.image` на образ своего sandbox/agent контейнера
|
||||
- в compose auth env vars нужны для startup config, но текущий MVP API еще не проверяет request token
|
||||
|
||||
## Как конфигурировать
|
||||
|
||||
### Источники конфига
|
||||
|
||||
Конфиг собирается в таком порядке:
|
||||
1. базовый YAML из `config/app.yaml`
|
||||
2. значения из `.env`
|
||||
3. process env vars поверх `.env`
|
||||
|
||||
То есть env vars имеют наивысший приоритет.
|
||||
|
||||
### Обязательные секреты
|
||||
|
||||
Нужны всегда:
|
||||
- `APP_API_TOKEN`
|
||||
- `APP_SIGNING_KEY`
|
||||
|
||||
Сейчас это startup config, а не активная request auth для `/api/v1/create` и `/api/v1/health`.
|
||||
То есть в текущем MVP токен не нужно передавать в HTTP headers для вызова этих endpoint.
|
||||
|
||||
### Основные секции YAML
|
||||
|
||||
В `config/app.yaml` и `config/docker-compose.yml` есть секции:
|
||||
- `app`
|
||||
- `http`
|
||||
- `logging`
|
||||
- `metrics`
|
||||
- `tracing`
|
||||
- `otel`
|
||||
- `docker`
|
||||
- `sandbox`
|
||||
- `security`
|
||||
|
||||
### Полезные env overrides
|
||||
|
||||
Чаще всего полезны:
|
||||
|
||||
#### Общие
|
||||
- `APP_NAME`
|
||||
- `APP_ENV`
|
||||
- `APP_HTTP_HOST`
|
||||
- `APP_HTTP_PORT`
|
||||
|
||||
#### Логирование и observability
|
||||
- `APP_LOGGING_LEVEL`
|
||||
- `APP_LOGGING_OUTPUT`
|
||||
- `APP_LOGGING_FORMAT`
|
||||
- `APP_LOGGING_FILE_PATH`
|
||||
- `APP_METRICS_ENABLED`
|
||||
- `APP_TRACING_ENABLED`
|
||||
- `APP_OTEL_SERVICE_NAME`
|
||||
- `APP_OTEL_LOGS_ENDPOINT`
|
||||
- `APP_OTEL_METRICS_ENDPOINT`
|
||||
- `APP_OTEL_TRACES_ENDPOINT`
|
||||
|
||||
#### Docker runtime
|
||||
- `APP_DOCKER_BASE_URL`
|
||||
|
||||
#### Sandbox
|
||||
- `APP_SANDBOX_IMAGE`
|
||||
- `APP_SANDBOX_TTL_SECONDS`
|
||||
- `APP_SANDBOX_CLEANUP_INTERVAL_SECONDS`
|
||||
- `APP_SANDBOX_CHATS_ROOT`
|
||||
- `APP_SANDBOX_DEPENDENCIES_HOST_PATH`
|
||||
- `APP_SANDBOX_LAMBDA_TOOLS_HOST_PATH`
|
||||
- `APP_SANDBOX_CHAT_MOUNT_PATH`
|
||||
- `APP_SANDBOX_DEPENDENCIES_MOUNT_PATH`
|
||||
- `APP_SANDBOX_LAMBDA_TOOLS_MOUNT_PATH`
|
||||
|
||||
#### Security
|
||||
- `APP_API_TOKEN_HEADER`
|
||||
- `APP_API_TOKEN`
|
||||
- `APP_SIGNING_KEY`
|
||||
|
||||
### Что важно в sandbox config
|
||||
|
||||
- `docker.base_url` — адрес Docker daemon
|
||||
- `sandbox.image` — образ sandbox контейнера
|
||||
- `sandbox.ttl_seconds` — TTL sandbox
|
||||
- `sandbox.cleanup_interval_seconds` — частота cleanup loop
|
||||
- `sandbox.chats_root` — корень chat directories
|
||||
- `sandbox.dependencies_host_path` — host path для dependency cache
|
||||
- `sandbox.lambda_tools_host_path` — host path для read-only lambda-tools
|
||||
- `sandbox.chat_mount_path` — путь внутри sandbox для chat volume
|
||||
- `sandbox.dependencies_mount_path` — путь внутри sandbox для dependency cache
|
||||
- `sandbox.lambda_tools_mount_path` — путь внутри sandbox для lambda-tools
|
||||
|
||||
## Основные команды
|
||||
|
||||
- `make install` — установить зависимости через `uv`
|
||||
- `make run` — локальный запуск
|
||||
- `make run-otel` — запуск с OTel endpoints из env
|
||||
- `make test` — `pytest`
|
||||
- `make lint` — `ruff`
|
||||
- `make typecheck` — `mypy`
|
||||
- `make pre-commit` — lint + typecheck + test
|
||||
- `make compose-build` — собрать compose images
|
||||
- `make compose-up` — поднять локальный stack
|
||||
- `make compose-down` — остановить stack
|
||||
- `make compose-logs` — смотреть логи
|
||||
- `make compose-ps` — смотреть статус сервисов
|
||||
|
||||
## Документация
|
||||
|
||||
### Гайды
|
||||
|
||||
- [Правила проекта и ограничения для агента](AGENTS.md)
|
||||
- [Кодстайл проекта для AI-агента](docs/CODESTYLE.md)
|
||||
- [Кодстайл проекта](docs/CODESTYLE.md)
|
||||
- [Чистая архитектура, SOLID, DIP, Protocol и repository](docs/CLEAN_ARCHITECTURE_RU.md)
|
||||
- [Логи, метрики и трейсы в этом проекте](docs/OBSERVABILITY_RU.md)
|
||||
- [Как чистая архитектура реализована здесь](docs/PROJECT_GUIDE_RU.md)
|
||||
|
|
@ -43,43 +275,24 @@ APP_API_TOKEN=local-api-token APP_SIGNING_KEY=local-signing-key make run
|
|||
- [003 Observability Via Interfaces](docs/003-observability-via-interfaces.md)
|
||||
- [004 Versioned HTTP API](docs/004-versioned-http-api.md)
|
||||
- [005 Early FastAPI OTel Instrumentation](docs/005-fastapi-otel-early-instrumentation.md)
|
||||
- [006 MVP Docker Sandbox Orchestration](docs/006-mvp-docker-sandbox-orchestration.md)
|
||||
- [007 Startup Sandbox Reconciliation](docs/007-startup-sandbox-reconciliation.md)
|
||||
- [008 Sandbox Lifecycle Observability](docs/008-sandbox-lifecycle-observability.md)
|
||||
|
||||
## Структура проекта
|
||||
## Для AI-агента
|
||||
|
||||
- `domain/` - core-сущности и доменные ошибки
|
||||
- `usecase/` - прикладные сценарии и порты
|
||||
- `repository/` - реализации repository
|
||||
- `adapter/config/` - загрузка и модели типизированного конфига
|
||||
- `adapter/observability/` - выбор runtime для logger, metrics и tracer
|
||||
- `adapter/otel/` - OpenTelemetry adapters
|
||||
- `adapter/di/` - composition root и singleton wiring
|
||||
- `adapter/http/fastapi/` - HTTP-схемы, dependencies, middleware и routers
|
||||
- `config/` - YAML-конфиг приложения и локального OTel collector
|
||||
Если ты меняешь проект как AI-агент, сначала прочитай:
|
||||
|
||||
## Для ИИ
|
||||
1. [AGENTS.md](AGENTS.md)
|
||||
2. [docs/CODESTYLE.md](docs/CODESTYLE.md)
|
||||
3. [docs/PROJECT_GUIDE_RU.md](docs/PROJECT_GUIDE_RU.md)
|
||||
4. [docs/CLEAN_ARCHITECTURE_RU.md](docs/CLEAN_ARCHITECTURE_RU.md)
|
||||
5. [docs/OBSERVABILITY_RU.md](docs/OBSERVABILITY_RU.md)
|
||||
6. релевантные ADR в `docs/`
|
||||
7. [tasks.md](tasks.md)
|
||||
|
||||
Если ты AI-агент и собираешься что-то менять в проекте, сначала прочитай документы в таком порядке:
|
||||
|
||||
1. [Правила проекта и ограничения агента](AGENTS.md) - обязательные правила работы в этом репозитории
|
||||
2. [Кодстайл проекта для AI-агента](docs/CODESTYLE.md) - границы слоев, стиль кода и правила зависимостей
|
||||
3. [Как чистая архитектура реализована здесь](docs/PROJECT_GUIDE_RU.md) - практическая карта проекта и типовые сценарии изменений
|
||||
4. [Чистая архитектура, SOLID, DIP, Protocol и repository](docs/CLEAN_ARCHITECTURE_RU.md) - базовые архитектурные принципы и примеры
|
||||
5. [Логи, метрики и трейсы в этом проекте](docs/OBSERVABILITY_RU.md) - читать перед любыми изменениями в observability, middleware и runtime wiring
|
||||
6. [ADR в `docs/`](docs/001-composition-root-and-lifetimes.md) - читать релевантные решения перед изменением архитектуры или startup wiring
|
||||
7. [План задач и история работ](tasks.md) - понять, что уже сделано, что отложено и какие ограничения были зафиксированы
|
||||
|
||||
Перед началом работы:
|
||||
|
||||
- Определи, в каком слое будет изменение: `domain/`, `usecase/`, `repository/` или `adapter/`
|
||||
- Убедись, что зависимости идут только внутрь
|
||||
- Не тащи FastAPI и OpenTelemetry во внутренние слои
|
||||
- Сначала изучи существующий код в нужной директории, потом вноси изменения
|
||||
- Если задача затрагивает архитектурное решение, сначала сверяйся с ADR и проектными правилами
|
||||
|
||||
## Запуск и команды
|
||||
|
||||
- Для локального запуска нужны `APP_API_TOKEN` и `APP_SIGNING_KEY`
|
||||
- `make run` запускает приложение локально
|
||||
- `make run-otel` запускает приложение с локальными OTel endpoints из env vars
|
||||
- `make pre-commit` запускает `ruff`, `mypy` и `pytest`
|
||||
- `make compose-up` поднимает приложение и локальный LGTM stack через Docker Compose
|
||||
Главные правила:
|
||||
- сначала определи слой изменения
|
||||
- зависимости только внутрь
|
||||
- не тащи FastAPI и OpenTelemetry во внутренние слои
|
||||
- архитектурные решения сверяй с ADR
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue