feat: Phase D-3 + D-4 — service_socket en Card, providers coexisten
Cierra el ciclo del swap automático Nous mock↔real:
- brahman-card: Card.service_socket: Option<PathBuf> y espejo en
WireCard. Path del data plane (distinto al Init). Cualquier
consumer que matchee con esta Card conecta directo, sin discovery
extra.
- brahman-broker: BrokeredCard propaga service_socket. Sin
participación en matching — sólo metadata.
- brahman-handshake::MatchEvent: nuevo campo
producer_service_socket. Server lo busca en BrokeredCard al emitir
Available.
- nouser-nous::transport: provider_socket_path(provider: &str)
devuelve nouser-nous-{provider}.sock por default. Mock y real
coexisten en sockets distintos (Phase D-4). default_socket_path()
conserva el comportamiento single-provider.
- Mock declara nouser-nous-mock.sock; real declara
nouser-nous-real.sock. La Card se construye DESPUÉS del bind.
- brahman-status imprime "socket:" por sesión cuando está presente.
Validación end-to-end:
$ ente-zero & nouser-nous-mock & nouser-nous-real &
$ ls /run/user/1001/nouser-nous-*.sock
nouser-nous-mock.sock
nouser-nous-real.sock
$ brahman-status
Sessions (2):
[ente] nouser.nous_real
socket: /run/user/1001/nouser-nous-real.sock
[ente] nouser.nous_mock
socket: /run/user/1001/nouser-nous-mock.sock
Pendiente (no crítico): nouser-core attract --remote usa todavía
NOUSER_NOUS_SOCKET hardcoded. Siguiente paso: subscribirse al
MatchEvent del broker y usar producer_service_socket directo, así
BRAHMAN_BROKER_CONTEXT=test/prod swapea provider sin tocar al
consumer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
//!
|
||||
//! Todos los mensajes que cruzan el wire son variantes de [`Frame`].
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use brahman_broker::MatchStrategy;
|
||||
use brahman_card::{TypeRef, WireCard, WitInterface};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -102,6 +104,12 @@ pub struct MatchEvent {
|
||||
pub via: MatchStrategy,
|
||||
/// `true` si fue resuelto por `pin_to`.
|
||||
pub pinned: bool,
|
||||
/// Socket de servicio (data plane) que declaró el productor.
|
||||
/// Si está presente, el consumer puede conectar directo sin
|
||||
/// pasar por discovery adicional. `None` si el productor no
|
||||
/// declaró service_socket en su Card.
|
||||
#[serde(default)]
|
||||
pub producer_service_socket: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
||||
@@ -297,6 +297,13 @@ impl Session {
|
||||
}
|
||||
|
||||
if let Some(m) = &new_match {
|
||||
// Resolvemos el service_socket del productor desde
|
||||
// la BrokeredCard; pasarlo en el evento permite al
|
||||
// consumer conectar directo sin discovery extra.
|
||||
let producer_service_socket = b
|
||||
.cards()
|
||||
.find(|c| c.session == m.producer.session)
|
||||
.and_then(|c| c.service_socket.clone());
|
||||
let event = MatchEvent {
|
||||
kind: MatchEventKind::Available,
|
||||
consumer_flow: input.name.clone(),
|
||||
@@ -306,6 +313,7 @@ impl Session {
|
||||
ty: m.ty.clone(),
|
||||
via: m.via,
|
||||
pinned: m.pinned,
|
||||
producer_service_socket,
|
||||
};
|
||||
let send_res = tx.try_send(Frame::MatchEvent(event));
|
||||
debug!(
|
||||
@@ -330,6 +338,7 @@ impl Session {
|
||||
ty: input.ty.clone(),
|
||||
via: brahman_broker::MatchStrategy::Exact,
|
||||
pinned: false,
|
||||
producer_service_socket: None,
|
||||
};
|
||||
let _ = tx.try_send(Frame::MatchEvent(event));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user