feat(sidecar): API reusable de discovery via broker
Promueve el patron ad-hoc discover_producer_socket que vivia inline en
'nouser attract --remote' a un modulo publico brahman_sidecar::discovery.
Cualquier consumer ahora puede preguntar al broker "quien provee este
TypeRef?" sin reimplementar el patron a mano.
API:
- build_consumer_card(label, flow_name, type_name) construye una Card
minima (Ente, Oneshot, Virtual) con un input flow. Asigna Ulid::new()
real (no nil), evitando colisiones en el broker.
- await_provider(card, timeout) async: conecta al init, espera
MatchEvent::Available, devuelve producer_service_socket, manda
Farewell. Ignora eventos Lost durante el await.
- await_provider_blocking(card, timeout) wrapper para mundos no-async
(CLIs, std-thread loops). Crea su propio runtime current_thread.
- ConsumerError tipado: Connect{socket,source}, NoProvider{flow,type_ref,
timeout}, Client(ClientError), Runtime(String). Adios al Box<dyn Error>.
Refactor en nouser daemon: discover_producer_socket inline (60 LOC) ->
5 LOC delegando en el helper. remote_embed ya no construye su propio
runtime.
Tests: 4 unitarios (id no-nil, id unico por llamada, formateo de Wit
TypeRef, fallback sin input). Build verde para sidecar y nouser-core.
This commit is contained in:
@@ -6,6 +6,62 @@ ratio/diff ver `git show <sha>`.
|
||||
|
||||
## 2026-05-09
|
||||
|
||||
### feat(sidecar): API reusable de discovery vía broker
|
||||
Promueve el patrón ad-hoc `discover_producer_socket` (que vivía
|
||||
inline en `nouser attract --remote`) a un módulo público
|
||||
`brahman_sidecar::discovery`. Cualquier consumer puede ahora
|
||||
preguntar al broker "¿quién provee este TypeRef?" con dos llamadas:
|
||||
|
||||
// Construir un consumer Card mínimo (Ente, Oneshot, Virtual)
|
||||
let card = brahman_sidecar::build_consumer_card(
|
||||
"mi-cli",
|
||||
"embed-result", // flow.input.name
|
||||
"json", // TypeRef::Primitive { name }
|
||||
);
|
||||
|
||||
// Bloqueante (CLIs, std-thread loops):
|
||||
let socket: PathBuf = brahman_sidecar::await_provider_blocking(
|
||||
card, Duration::from_secs(3),
|
||||
)?;
|
||||
// O async (módulos con runtime tokio propio):
|
||||
let socket = brahman_sidecar::await_provider(card, timeout).await?;
|
||||
|
||||
API:
|
||||
- `build_consumer_card(label, flow_name, type_name) -> Card`
|
||||
abstrae la verbosidad del struct-literal repetido en cada caller.
|
||||
Genera un `id: Ulid::new()` real (no nil → seguro contra
|
||||
colisiones en el broker).
|
||||
- `await_provider(card, timeout) -> Result<PathBuf, ConsumerError>`
|
||||
conecta al init, espera `MatchEvent::Available`, devuelve
|
||||
`producer_service_socket`, manda Farewell. Ignora eventos
|
||||
`Lost` durante el await (no aplican al arranque).
|
||||
- `await_provider_blocking(card, timeout)` arma su propio
|
||||
runtime `current_thread` para mundos no-async.
|
||||
- `ConsumerError` con variantes tipadas: `Connect { socket, source }`,
|
||||
`NoProvider { flow, type_ref, timeout }`, `Client(ClientError)`,
|
||||
`Runtime(String)`. Adiós al `Box<dyn Error>` de antes.
|
||||
|
||||
Refactor en `nouser daemon`:
|
||||
- `discover_producer_socket` (60 LOC inline en `bin/nouser.rs`) → 5
|
||||
líneas que delegan en el helper.
|
||||
- `remote_embed` ya no construye su propio runtime tokio.
|
||||
|
||||
Próximo consumer natural: `nouser-explorer`. Hoy renderea
|
||||
`StatusSnapshot` vía socket admin (introspección pura). El día que
|
||||
quiera **interactuar** con un Ente — p. ej., disparar un re-embed
|
||||
desde la UI — usa este helper para resolver el socket del provider
|
||||
sin hardcodear paths.
|
||||
|
||||
Nota sobre identidad: este commit fuerza `Ulid::new()` para los
|
||||
consumer Cards generados, evitando la trampa documentada del
|
||||
`Card::default()` que devuelve `Ulid::nil()`. La fijación global de
|
||||
`Default` queda como cleanup separado (requiere auditar que ningún
|
||||
caller dependa del determinismo de `nil`).
|
||||
|
||||
Tests: 4 unitarios nuevos en `discovery::tests` (id no-nil, id
|
||||
único por llamada, formateo de TypeRef::Wit, fallback sin input).
|
||||
Workspace verde.
|
||||
|
||||
### feat(nouser+sidecar): watcher con debounce + re-publish al broker
|
||||
Cierra las dos limitaciones del watcher previo: ya no spamea N veces por
|
||||
una sola edición, y el broker ve los cambios estructurales en lugar de
|
||||
|
||||
Reference in New Issue
Block a user