Skip to content

Runtime e deploy

Quando usar esta página

Use esta trilha quando você precisa operar o Atreides como serviço:

  • validar contratos HTTP da API command-side;
  • testar JWT e escopo por tenant;
  • disparar workflows no Airflow;
  • executar as etapas de treino como jobs separados;
  • inspecionar health, readiness, métricas e DAG runs.

Para o desenvolvimento diário, prefira Quickstart.

Comandos principais

Terminal window
just db-init
just db-migrations-dry-run
just seed-local-model-definition
just serve-http

Comandos auxiliares:

Terminal window
just config-validate <manifest.json>
just config-apply <manifest.json>
just config-apply-manifests

just db-init aplica as migrations ClickHouse pendentes e registra as versões em schema_migrations. Use just db-migrations-dry-run para listar as versões que seriam aplicadas antes de executar contra um ambiente. just seed-local-model-definition cria a definição determinística usada pelos exemplos locais, e just serve-http sobe a API carregando .env pelo just.

Configurações por organização

O diretório versionado config/orgs/ é o ponto padrão para configurações por organização aplicadas em CI/CD. Cada organização deve ter um subdiretório próprio com um manifest.json no mesmo contrato usado por just config-apply:

config/orgs/<organization_slug>/manifest.json

Enquanto não houver manifests reais, o diretório permanece versionado com .gitkeep e just config-apply-manifests termina sem aplicar nada. Quando houver manifests, o comando percorre os subdiretórios em ordem determinística e ativa as revisions de configuração no ClickHouse usando DATABASE_URL.

Esses manifests são a configuração operacional dos ModelDefinitions que a organização poderá disparar. Um ModelDefinition representa uma política de forecast para uma população de séries: receita de projeção, horizonte, validação, features, estratégias, métricas e promoção. Depois que as revisões são aplicadas, os triggers de treino e predição escolhem uma definição por model_definition_id.

O fluxo atual não tem roteamento granular por série no runtime. O trigger não envia uma lista de SeriesKeys. Ele envia organization_id, model_definition_id e snapshot_id; a definição escolhida resolve sua series_projection_recipe; e o workflow processa todas as séries que essa receita produz a partir do snapshot.

Variáveis de ambiente mínimas

Terminal window
export DATABASE_URL=clickhouse://default@127.0.0.1:8123/atreides
export JWT_SECRET=dev-jwt-secret-with-sufficient-length
export AIRFLOW_API_BASE_URL=http://127.0.0.1:8080
export AIRFLOW_LOCAL_DEV_AUTO_AUTH=true
export MLFLOW_TRACKING_URI=http://127.0.0.1:5000
export DEMAND_STORAGE_BACKEND=s3
export DEMAND_INGESTION_BUCKET=atreides-demand
export ARTIFACT_STORE_BACKEND=s3
export MODEL_ARTIFACT_BUCKET=atreides-artifacts
export S3_ENDPOINT_URL=http://127.0.0.1:9000
export S3_REGION=us-east-1
export S3_ACCESS_KEY_ID=minioadmin
export S3_SECRET_ACCESS_KEY=minioadmin
export S3_USE_SSL=false
# Opcional: habilita exportacao OTLP/HTTP de traces para um collector.
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318

API HTTP:

  • exige DATABASE_URL;
  • exige JWT_SECRET;
  • exige AIRFLOW_API_BASE_URL;
  • aceita AIRFLOW_API_VERSION, padrão v2;
  • aceita AIRFLOW_MODEL_TRAINING_DAG_ID, padrão model_training;
  • aceita AIRFLOW_BEARER_TOKEN para ambientes com token explícito;
  • aceita AIRFLOW_LOCAL_DEV_AUTO_AUTH=true apenas para dev local com Airflow standalone;
  • não executa treino, materialização nem retry.

Jobs do Airflow:

  • exigem DATABASE_URL;
  • exigem MLFLOW_TRACKING_URI;
  • exigem DEMAND_STORAGE_BACKEND;
  • em filesystem, exigem DEMAND_STORAGE_ROOT;
  • em s3, exigem DEMAND_INGESTION_BUCKET;
  • em artifact store s3, exigem MODEL_ARTIFACT_BUCKET;
  • quando usar MinIO/S3 compatível local, configure também S3_ENDPOINT_URL, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY e S3_USE_SSL=false.

Airflow:

  • carrega DAGs de src/infra/dags;
  • precisa de PYTHONPATH=src ou equivalente;
  • executa os entrypoints em src/infra/jobs;
  • é o dono de retries e estado operacional do workflow.

Observabilidade

O processo HTTP expõe GET /metrics fora do namespace /v1, portanto sem JWT, para scrape Prometheus. A resposta inclui métricas de runtime Python e as métricas operacionais do Atreides emitidas pelo adapter OpenTelemetry:

Métrica PrometheusUso
forecast_engine_operation_started_totalcontador de operações iniciadas
forecast_engine_operation_completed_totalcontador de operações concluídas com sucesso
forecast_engine_operation_failed_totalcontador de falhas por operação e tipo de erro
forecast_engine_operation_activegauge de operações em andamento no processo
forecast_engine_operation_duration_secondshistograma de duração por operação
forecast_engine_operation_serieshistograma de séries processadas por operação
forecast_engine_model_versionhistograma da versão de modelo tocada pela operação

As labels de métrica ficam restritas a dimensões de baixa cardinalidade: operation, outcome, workflow, error_type, http_method, http_route e http_status_code. Identificadores como organization_id, model_definition_id e snapshot_id entram nos logs e spans, mas não viram labels Prometheus.

As operações instrumentadas hoje são:

  • http.request: request HTTP com método, rota FastAPI templated e status;
  • training.workflow.submit: API HTTP criou snapshot e disparou a DAG de treino;
  • prediction.workflow.submit: API HTTP criou snapshot e disparou a DAG de predição;
  • training.candidates.execute: job de treino resolveu configuração, treinou candidatas e persistiu instâncias;
  • prediction.forecast.execute: job batch executou forecasts e persistiu ForecastRuns.

O runtime também cria spans OpenTelemetry para as execuções de treino e forecast. Para exportar traces e métricas OTLP em produção, configure OTEL_EXPORTER_OTLP_ENDPOINT no processo HTTP e nos jobs. Sem essa variável, o HTTP continua expondo métricas via /metrics, mas os jobs de Airflow ficam limitados a logs e spans/métricas locais no processo. Com OTLP habilitado, o shutdown dos jobs força o flush dos exporters antes de fechar os recursos.

Fluxo HTTP manual

  1. Gere um token local:
Terminal window
just setup-local-auth 01956c73-9c1f-7fb7-94b1-a2c5bc65d901 local-operator
  1. Dispare treino em POST /v1/model-definitions/{model_definition_id}/training-jobs informando input_path e source_format.
  2. A API cria o snapshot processing e dispara a DAG model_training.
  3. Acompanhe o run no Airflow pelo run_id retornado.
  4. Acompanhe os resultados duráveis em ClickHouse, MLflow, storage e nas projeções externas do ambiente.

Regras operacionais:

  • toda rota /v1/* exige JWT bearer;
  • o organization_id do token é a fonte de verdade do tenant;
  • model_definition_id seleciona a política de forecast que será executada;
  • a execução cobre todas as séries projetadas por essa definição no snapshot;
  • não há parâmetro HTTP para limitar treino a uma lista de séries individuais;
  • preparação de snapshot e treino rodam em jobs chamados pelo Airflow, não no processo HTTP;
  • retry e reexecução pertencem ao Airflow;
  • o Atreides permanece write-side para snapshots, treino e promoção; consultas operacionais detalhadas vivem fora deste serviço.

Contrato OpenAPI

A especificação OpenAPI é gerada pelo código FastAPI em src/infra/http e é a referência operacional do contrato HTTP. Com a API em execução, use:

  • GET /openapi.json para consumir a especificação;
  • GET /docs para a UI Swagger;
  • GET /redoc para a UI ReDoc;
  • GET /healthz para readiness do processo e dependências configuradas.

O schema documenta o security scheme BearerAuth, os operationId estáveis das rotas de comando, exemplos de payload e respostas de erro esperadas. Se um campo do contrato HTTP mudar, atualize primeiro os DTOs, rotas e docstrings em src/infra/http, depois sincronize esta documentação.

Seed customizado

Para o seed local padrão, prefira:

Terminal window
just seed-local-model-definition

Se precisar customizar ids ou seletor, rode o módulo diretamente:

Terminal window
PYTHONPATH=src uv run python -m infra.persistence.clickhouse.seed \
--database-url "$DATABASE_URL" \
--organization-id "<organization_id>" \
--model-definition-id "<model_definition_id>" \
--name "mvp-seasonal-naive"

Checklist de runtime

  • banco do Atreides atualizado com a migration mais recente;
  • Airflow iniciado e carregando a DAG model_training;
  • ao menos um ModelDefinition persistido e configurado por organização atendida;
  • operadores sabem qual model_definition_id corresponde a cada população de séries;
  • AIRFLOW_API_BASE_URL configurado no processo HTTP;
  • token de Airflow configurado por AIRFLOW_BEARER_TOKEN em runtime real ou AIRFLOW_LOCAL_DEV_AUTO_AUTH=true em dev local;
  • MLFLOW_TRACKING_URI válido para os jobs;
  • backend de demanda configurado para os jobs;
  • backend de artefatos configurado para os jobs;
  • S3 compatível configurado quando usar MinIO;
  • JWT configurado para todo /v1/*;
  • /healthz respondendo sem erro.

Onde continuar