feat: segundo módulo (nakui) + admin API + brahman-status
Dos cosas en una sesión, en el orden discutido:
(1) Segundo módulo brahman vivo: nakui-core
- crates/modules/nakui/core/Cargo.toml: deps brahman-card,
brahman-sidecar, ulid.
- crates/modules/nakui/core/src/bin/nakui.rs: brahman_card_for_nakui()
construye una Card como Lifecycle::Daemon, Supervision::Restart,
flow.input "command" (json) + flow.output "report" (json). El
cmd_run llama brahman_sidecar::spawn antes de levantar el server
de nakui.
(2) crates/shared/brahman-sidecar (estrena crates/shared/)
Boilerplate del sidecar extraído (DRY): el thread con tokio current
thread runtime, conexión vía Client::connect, ping loop. Yahweh y
nakui ahora consumen este crate. API:
- spawn(card) fire-and-forget
- spawn_with_handle(config) con JoinHandle
Example "presence" útil para demos: módulo dummy con label tomado
del primer arg que se queda vivo hasta SIGTERM.
(3) crates/core/brahman-admin: observabilidad del broker
Socket Unix paralelo en \$BRAHMAN_ADMIN_SOCKET (default
\$XDG_RUNTIME_DIR/brahman-admin.sock). Cada conexión recibe un
StatusSnapshot JSON line-delimited y se cierra. Compatible con nc/socat.
- StatusSnapshot { server, protocol, init_attached, sessions, matches }
- server::AdminServer
- client::query(path)
- example "brahman-status" CLI
(4) Wiring de ente-zero
En primordial_loop, junto al handshake server, ahora también levanta
AdminServer con misma política de degradación grácil.
(5) brahman-broker: BrokeredCard ahora incluye lifecycle. Endpoint y
Match derivan Serialize/Deserialize. Nuevo método cards() expone
iterador de BrokeredCard para que el admin pueda construir snapshots.
(6) brahman-card: re-export pub use ulid::* para que módulos no
necesiten depender de ulid directamente.
(7) yahweh-shell migrado al sidecar compartido. Su brahman_client.rs
pasa de 96 a 53 líneas: sólo declara la Card, delega el spawn.
Demo end-to-end:
$ ente-zero &
$ presence demo.producer &
$ presence demo.consumer &
$ brahman-status
Init: server=0.1.0 protocol=0.1.0 attached=true
Sessions (2):
01KR42TY1J... demo.producer lifecycle=Daemon priority=Normal
01KR42TY1K... demo.consumer lifecycle=Daemon priority=Normal
Matches (2):
demo.producer.in ← demo.consumer.out via Exact
demo.consumer.in ← demo.producer.out via Exact
El broker matchea bidireccional por tipo. El admin lo expone.
Tests: 27/27. cargo check --workspace: 0 errores.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use brahman_card::{Card, Flow, Priority, TypeRef};
|
||||
use brahman_card::{Card, Flow, Lifecycle, Priority, TypeRef};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ulid::Ulid;
|
||||
|
||||
@@ -60,10 +60,11 @@ pub struct BrokerConfig {
|
||||
}
|
||||
|
||||
/// Vista mínima de una Card que el broker necesita.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BrokeredCard {
|
||||
pub session: SessionId,
|
||||
pub label: String,
|
||||
pub lifecycle: Lifecycle,
|
||||
pub priority: Priority,
|
||||
pub inputs: Vec<Flow>,
|
||||
pub outputs: Vec<Flow>,
|
||||
@@ -74,6 +75,7 @@ impl BrokeredCard {
|
||||
Self {
|
||||
session,
|
||||
label: card.label.clone(),
|
||||
lifecycle: card.lifecycle,
|
||||
priority: card.priority,
|
||||
inputs: card.flow.input.clone(),
|
||||
outputs: card.flow.output.clone(),
|
||||
@@ -82,14 +84,14 @@ impl BrokeredCard {
|
||||
}
|
||||
|
||||
/// Punto extremo de un flujo: qué sesión + nombre del flow dentro de su Card.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Endpoint {
|
||||
pub session: SessionId,
|
||||
pub flow_name: String,
|
||||
}
|
||||
|
||||
/// Match concreto entre un consumidor y un productor.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Match {
|
||||
pub consumer: Endpoint,
|
||||
pub consumer_label: String,
|
||||
@@ -147,6 +149,11 @@ impl Broker {
|
||||
self.cards.keys().copied()
|
||||
}
|
||||
|
||||
/// Iterador sobre las Cards registradas (vista compartida).
|
||||
pub fn cards(&self) -> impl Iterator<Item = &BrokeredCard> + '_ {
|
||||
self.cards.values()
|
||||
}
|
||||
|
||||
/// Busca el mejor productor para un input específico de un consumidor.
|
||||
///
|
||||
/// Algoritmo:
|
||||
|
||||
Reference in New Issue
Block a user