Структура app-config.yaml
Нормативная спецификация не фиксирует конкретные секции — любая верхнеуровневая секция определяется приложением-потребителем. Ниже — соглашения по именованию и структурированию, выработанные экосистемой dagstack.
Верхнеуровневые секции общего назначения
Набор секций, которые встречаются в большинстве dagstack-приложений независимо от домена (биллинг, аналитика, чат-бот, индексатор, сервис нотификаций, и т.д.):
| Секция | Назначение | Обязательно |
|---|---|---|
app | Метаинформация приложения (name, tagline). | Нет, но рекомендуется. |
dagstack | Настройки plugin-system (plugin_dirs, переопределения). | Если используется plugin-system. |
logging | Структурированный логгер (dagstack/logger-spec). | Рекомендуется. |
tenancy | Модель мульти-клиентности (dagstack/tenancy-spec). | Если multi-tenant. |
database | Подключение к БД (host, port, pool_size). | Domain-specific. |
cache | Redis / memcached / локальный кеш. | Domain-specific. |
metrics | Prometheus / OTLP endpoint. | Рекомендуется в production. |
<kind>.<name> | Секция конкретного плагина вида kind с именем name. | plugin-system apps. |
Всё остальное — domain-specific секции, специфичные для приложения (billing, notifications, workers, auth, rag, email, scheduler, api, и т.д.).
Соглашения по именованию
| Правило | Пример |
|---|---|
snake_case для ключей | base_url, max_retries |
| Существительное в ед. числе | database, не databases |
Boolean без is_ / has_ | enabled, не is_enabled |
| Timestamps в ISO 8601 | "2026-04-21T12:00:00Z" |
Длительности с суффиксом _s / _ms / _min | timeout_s: 30, cache_ttl_min: 15 |
Размеры с суффиксом _bytes / _mb / _gb | max_upload_mb: 10 |
Пример: service-бэкенд
app:
name: "order-service"
tagline: "Обработчик заказов"
dagstack:
plugin_dirs:
- plugins/
database:
host: "${DB_HOST:-localhost}"
port: "${DB_PORT:-5432}"
name: "${DB_NAME:-orders}"
user: "${DB_USER}"
password: "${DB_PASSWORD}"
pool_size: 20
cache:
url: "${REDIS_URL:-redis://localhost:6379/0}"
ttl_min: 15
api:
host: "0.0.0.0"
port: 8080
cors_origins:
- "https://app.example.com"
workers:
concurrency: 8
queue_name: "orders"
logging:
level: "${LOG_LEVEL:-INFO}"
format: "${LOG_FORMAT:-json}"
tenancy:
mode: "${TENANCY_MODE:-single}"
Пример: data-processing-приложение с plugin-system
app:
name: "data-indexer"
dagstack:
plugin_dirs:
- plugins/
# Секции конкретных плагинов — по правилу <kind>.<name>:
source:
s3_bucket: # секция плагина source.s3_bucket
bucket: "${INGEST_BUCKET}"
region: "eu-central-1"
postgres: # секция плагина source.postgres
url: "${SOURCE_DB_URL}"
processor:
normalize: # секция плагина processor.normalize
locale: "en_US"
enrich: # секция плагина processor.enrich
api_key: "${ENRICHMENT_API_KEY}"
sink:
elasticsearch: # секция плагина sink.elasticsearch
url: "${ES_URL}"
index: "documents"
Каждый плагин читает свою секцию <kind>.<name> через config.getSection() — общий паттерн независимо от домена приложения.
Domain-specific примеры
dagstack одинаково подходит для разных классов приложений — несколько типичных конфигов:
E-commerce-биллинг (расчёт платежей):
billing:
provider: "${BILLING_PROVIDER:-stripe}"
webhook_secret: "${BILLING_WEBHOOK_SECRET}"
currency: "USD"
tax_rates:
default: 0.20
reduced: 0.05
Агрегатор нотификаций:
notifications:
email:
smtp_host: "${SMTP_HOST}"
from_address: "no-reply@example.com"
sms:
api_key: "${SMS_API_KEY}"
from_number: "+1-555-0100"
push:
fcm_key: "${FCM_KEY}"
AI / RAG-платформа (один из возможных кейсов):
llm:
base_url: "${OPENAI_BASE_URL:-https://api.openai.com/v1}"
api_key: "${OPENAI_API_KEY}"
model: "${OPENAI_MODEL:-gpt-4o-mini}"
vector_store:
url: "${QDRANT_URL:-http://localhost:6333}"
api_key: "${QDRANT_API_KEY}"
retrieval:
top_k: 10
min_score: 0.55
Во всех трёх кейсах механизмы конфиг-стека те же — слои, env-интерполяция, getSection(), подписки на изменения. Знания, специфичные для домена, живут в приложении, не в конфиг-стеке.
Правила merge для массивов
dagstack:
plugin_dirs:
- plugins/
- examples/plugins/
dagstack:
plugin_dirs:
- /opt/dagstack/plugins/
После merge (DAGSTACK_ENV=production):
dagstack:
plugin_dirs:
- /opt/dagstack/plugins/ # массив полностью заменён
Массив не конкатенируется. См. Слои — правила merge.
Null в слое-переопределении
cache:
redis:
url: "redis://localhost:6379/0"
cache:
redis: null # явное отключение кеша локально
null в слое-переопределении явно перекрывает значение базового слоя. Отсутствие ключа в переопределении — не изменяет base.
Комментарии
YAML поддерживает #-комментарии. Хорошая практика:
api:
# Максимум запросов в секунду на клиента. По умолчанию 10,
# для internal-сервисов можно поднять до 100.
rate_limit_rps: 10
Комментарии помогают оператору понять назначение неочевидных полей.
См. также
- Слои конфигурации — правила merge.
- Подстановка env-переменных — синтаксис
${VAR}. - Объявить секцию — pydantic / zod schema для своей секции.