fad4006f60
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
173 lines
8.6 KiB
Markdown
173 lines
8.6 KiB
Markdown
---
|
|
id: "0095"
|
|
title: "Frontend C++ ImGui para `dag_engine`"
|
|
status: pendiente
|
|
type: feature
|
|
domain:
|
|
- cpp-stack
|
|
- frontend
|
|
scope: multi-app
|
|
priority: alta
|
|
depends: []
|
|
blocks: []
|
|
related: []
|
|
created: 2026-05-17
|
|
updated: 2026-05-17
|
|
tags: []
|
|
---
|
|
# 0095 — Frontend C++ ImGui para `dag_engine`
|
|
|
|
**Status:** pendiente
|
|
**Created:** 2026-05-15
|
|
**Type:** app
|
|
**Blocks:** 0096 (data_factory) — necesita frontend C++ unificado para scheduler
|
|
**Related:** `apps/dag_engine` (Go + Vite/React actual), `projects/fn_monitoring/apps/registry_dashboard` (referencia pubsub)
|
|
|
|
## Problema
|
|
|
|
`dag_engine` (alternativa propia a Dagu, ya existente) hoy sirve dos modos:
|
|
- CLI (`run/list/status/validate/server`).
|
|
- Web (Vite + React + Mantine en `apps/dag_engine/frontend/`).
|
|
|
|
El resto del ecosistema de monitorizacion del registry esta en C++ ImGui (`registry_dashboard`, `call_monitor`, futuro `data_factory`). Forzar al usuario a saltar al navegador para gestionar/observar DAGs rompe el flujo. Ademas la app `data_factory` (issue 0096) necesita embeber vista de scheduler para mostrar que DAG dispara cada extractor — si esa vista es web, no encaja en su UI ImGui.
|
|
|
|
## Objetivo
|
|
|
|
Anadir app C++ ImGui `dag_engine_ui` que cubre el caso "ver/lanzar/inspeccionar DAGs" con el **mismo backend** (`dag_engine server` HTTP+WS) y reusa el patron pubsub de `registry_dashboard` (HTTP REST + WebSocket live updates).
|
|
|
|
NO sustituye el frontend web — convive. El web sigue util para acceso remoto al VPS; el C++ es para uso local en escritorio.
|
|
|
|
## Piezas
|
|
|
|
### Backend (apps/dag_engine, cambios minimos)
|
|
|
|
1. **WS hub `DagRunHub`** en `apps/dag_engine/events.go` siguiendo el patron de `CallMonitorHub` (sqlite_api/events.go):
|
|
- Hub global con N subscribers WS.
|
|
- Ticker arranca solo con >=1 subscriber.
|
|
- Polling watermark a tabla `dag_runs` + `dag_step_results` cada 500ms.
|
|
- Snapshot inicial al conectar (lista DAGs + ultimos runs).
|
|
- Broadcast de eventos: `run_started`, `step_completed`, `run_finished`, `schedule_updated`.
|
|
2. **Endpoint** `GET /api/ws/dagruns` (upgrade WebSocket).
|
|
3. **Endpoint** `POST /api/dags/:name/run` (Run Now) — ya existe; verificar que devuelve `run_id` inmediato y el hub broadcastea el progreso.
|
|
4. **CORS** ya abierto en `middleware.go`.
|
|
|
|
### App C++ ImGui (`apps/dag_engine_ui/`)
|
|
|
|
Scaffolding via `fn run init_cpp_app dag_engine_ui --desc "Frontend ImGui para dag_engine"`.
|
|
|
|
1. **Capa HTTP**: `data_http.{cpp,h}` clona patron de `registry_dashboard/data_http.{cpp,h}` (cpp-httplib + nlohmann/json). Endpoints:
|
|
- `GET /api/dags` -> lista DAGs.
|
|
- `GET /api/dags/:name` -> detalle.
|
|
- `GET /api/dags/:name/runs` -> historial.
|
|
- `GET /api/runs/:id` -> timeline pasos.
|
|
- `POST /api/dags/:name/run` -> dispara.
|
|
- `POST /api/dags/:name/validate` -> valida YAML.
|
|
2. **Capa WS**: `ws_client.{cpp,h}` reusado tal cual de `registry_dashboard`. Conecta a `ws://127.0.0.1:8090/api/ws/dagruns`.
|
|
3. **Tabs** (panels via `cfg.panels`):
|
|
- **DAG List** — tabla: name, schedule (cron), last_status, last_run_at, next_run_at, tags. Reusa `table_view_cpp_viz`. Click fila -> DAG Detail.
|
|
- **DAG Detail** — header + metadata + boton "Run Now" + historial ultimos N runs (`table_view_cpp_viz`). Reusa `page_header_cpp_core`, `button_cpp_core`, `badge_cpp_core`.
|
|
- **Run Detail** — timeline de steps con stdout/stderr expandible. Reusa `tree_view_cpp_core` y un componente nuevo `timeline_cpp_viz` si no existe (delegar a fn-constructor).
|
|
- **Schedule** — vista cron: para cada DAG con `schedule:` lo siguiente que va a disparar (`next_cron_time_go_core`). Mini-calendario opcional.
|
|
- **Health** — kpis: runs_24h, success_rate, p95_duration, failed_runs. Reusa `kpi_card_cpp_viz`.
|
|
4. **Live updates**: WS recibe eventos -> push a ringbuffer en memoria -> tabs leen del ringbuffer en cada `render`. Run en curso se anima (spinner en columna status).
|
|
5. **Config**: `--api-url http://127.0.0.1:8090` (default localhost). Persistencia en `app_settings.ini` (gestionado por `app_settings_cpp_core`).
|
|
|
|
### Frontmatter `app.md`
|
|
|
|
```yaml
|
|
---
|
|
name: dag_engine_ui
|
|
lang: cpp
|
|
domain: tui
|
|
description: "Frontend ImGui para dag_engine. Lista, lanza e inspecciona DAGs con live updates via WS. Equivalente local al frontend web."
|
|
tags: [imgui, dashboard, dag, scheduler, http, websocket]
|
|
uses_functions:
|
|
- kpi_card_cpp_viz
|
|
- bar_chart_cpp_viz
|
|
- table_view_cpp_viz
|
|
- dashboard_panel_cpp_core
|
|
- dashboard_grid_cpp_core
|
|
- page_header_cpp_core
|
|
- badge_cpp_core
|
|
- button_cpp_core
|
|
- icon_button_cpp_core
|
|
- toolbar_cpp_core
|
|
- text_input_cpp_core
|
|
- select_cpp_core
|
|
- tree_view_cpp_core
|
|
- empty_state_cpp_core
|
|
- modal_dialog_cpp_core
|
|
- toast_cpp_core
|
|
uses_types: []
|
|
framework: "imgui"
|
|
entry_point: "main.cpp"
|
|
dir_path: "apps/dag_engine_ui"
|
|
repo_url: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/dataforge/dag_engine_ui"
|
|
---
|
|
```
|
|
|
|
Tag de grupo: anadir `scheduler` (grupo nuevo si >=3 funciones lo respaldan; revisar antes — si no, dejar plano).
|
|
|
|
### Funciones nuevas a delegar (estimacion)
|
|
|
|
- `timeline_cpp_viz` — componente ImGui que pinta pasos de un run con duracion + status + expand stdout/stderr. Reusable por `data_factory` v2.
|
|
- `cron_explain_go_core` (puro) — dado `"0 */15 * * *"` devuelve string humano "every 15 min". Usado en DAG List.
|
|
- `http_poll_json_cpp_core` (impuro) — wrapper sobre cpp-httplib que hace GET periodico con backoff y publica deltas via callback. Reusable.
|
|
|
|
Si patrones se repiten en `registry_dashboard` (cabecera HTTP+WS hibrido) -> proposal de extraer un mini-cliente comun `cpp/functions/core/http_ws_client.{cpp,h}`. NO crear inline.
|
|
|
|
## Aceptacion
|
|
|
|
- `fn run init_cpp_app dag_engine_ui` ejecutado, scaffolding limpio.
|
|
- `dag_engine server` expone `/api/ws/dagruns` (hub con register/unregister/snapshot/delta).
|
|
- App C++ compila en Linux y Windows (`build_cpp_windows_bash_infra dag_engine_ui`).
|
|
- Smoke: con `dag_engine server` corriendo y un DAG ejemplo, abrir app -> ve DAG en lista, click "Run Now" -> timeline aparece en vivo sin refresh.
|
|
- `e2e_checks` en `app.md`:
|
|
- `build_cmake` — `cmake --build cpp/build -j --target dag_engine_ui`.
|
|
- `self_test` — `./dag_engine_ui --self-test` arranca, valida conexion HTTP a `dag_engine`, sale 0/1.
|
|
- `pytest` opcional — script que arranca `dag_engine server` con DAG dummy, lanza UI headless (xvfb), spera evento WS, sale 0/1.
|
|
- `fn doctor cpp-apps` no reporta drift sobre `dag_engine_ui`.
|
|
- `uses_functions` declarado en `app.md` y los `.cpp` del registry listados en `CMakeLists.txt` coinciden (`fn doctor uses-functions`).
|
|
|
|
## No-objetivos
|
|
|
|
- Editar YAML de DAGs desde la UI (v2 — por ahora solo lectura + Run Now + Validate).
|
|
- Generar nuevos DAGs visualmente tipo drag&drop (v2).
|
|
- Sustituir el frontend web — convive.
|
|
- Soporte multi-engine (varios `dag_engine` remotos). Asume 1 backend local.
|
|
|
|
## Riesgos
|
|
|
|
| Riesgo | Mitigacion |
|
|
|---|---|
|
|
| WS hub anade peso al binario `dag_engine` | Mismo patron que `sqlite_api` (~150 LOC); negligible. |
|
|
| `cpp-httplib` no soporta WS upgrade limpio | `registry_dashboard/ws_client.cpp` ya implementa RFC 6455 manual sobre TCP. Reusar tal cual. |
|
|
| Doble UI (web + C++) -> deriva | Un solo backend, mismos endpoints. Si web cambia, C++ se entera por contrato HTTP. |
|
|
| Cron parser duplica logica si se anade `cron_explain` | Funcion pura nueva, atomica, justificada (UX). |
|
|
|
|
## Dependencias
|
|
|
|
- `apps/dag_engine` corriendo y aceptando conexiones.
|
|
- `cpp/functions/viz/*` y `cpp/functions/core/*` ya existentes (ver `uses_functions`).
|
|
- `cpp-httplib` y `nlohmann/json` vendored (igual que `registry_dashboard`).
|
|
|
|
## Plan de ejecucion (sub-tareas)
|
|
|
|
1. **Backend**: anadir `events.go` con `DagRunHub` + handler WS en `dag_engine`. Commit.
|
|
2. **Scaffolding**: `fn run init_cpp_app dag_engine_ui`. Commit.
|
|
3. **Capa HTTP**: copiar y adaptar `data_http.{cpp,h}` desde `registry_dashboard`. Endpoints DAG. Commit.
|
|
4. **Capa WS**: copiar `ws_client.{cpp,h}` tal cual. Conectar a `/api/ws/dagruns`. Commit.
|
|
5. **Tabs DAG List + Detail + Run Detail**. Commit por tab.
|
|
6. **Schedule + Health tabs**. Commit.
|
|
7. **Funciones nuevas** (`timeline_cpp_viz`, `cron_explain_go_core`, `http_poll_json_cpp_core`) — delegar a fn-constructor en paralelo en mismo turno. Commit por funcion.
|
|
8. **e2e_checks + redeploy_cpp_app_windows**. Commit final.
|
|
|
|
Cada paso: rama TBD propia (`issue/0095-<slug>`), merge `--no-ff` a master.
|
|
|
|
## Telemetria objetivo
|
|
|
|
Tras este issue:
|
|
- `dag_engine_ui` aparece en `function_stats` con `calls > 0` (lanzamientos via `is_cpp_app_running_windows_bash_infra`).
|
|
- `cron_explain_go_core` con `consumer_apps_count >= 1`.
|
|
- `timeline_cpp_viz` con consumidor declarado en `uses_functions` de `dag_engine_ui` + candidato a reuso en `data_factory` (issue 0096).
|