feat(brahman-net+handshake): stop_providing automatico en cleanup

Cierra el pendiente conocido del DHT: hasta ahora cuando una sesion
con outputs cerraba (Farewell, EOF, error), el record que la
anunciaba en el DHT seguia vivo hasta su TTL natural (~24h en kad
default). Consumers remotos podian descubrir un peer "vivo" que ya
no servia nada.

Cambios:
- BrahmanNet::stop_providing(key) (nuevo): contraparte simetrica de
  start_providing. Manda Command::StopProviding al swarm que llama
  kad.stop_providing(&key). Borra el record local al instante;
  replicas remotas siguen expirando por TTL (kad no expone retraccion
  cross-peer, simetrico al hecho de que start_providing tambien
  propaga eventualmente).
- brahman_handshake::network::withdraw_outputs(net, card) (nuevo):
  contraparte de announce_outputs. Itera card.flow.output y llama
  net.stop_providing(flow_dht_key(...)) por cada uno.
- server::cleanup: extrae la ResolvedCard removida del registro de
  sesiones (en lugar de descartarla) y, si config.net esta set,
  llama withdraw_outputs(net, &card) antes de broadcast_match_diffs.

Tests: nuevo E2E dht_discovery_withdraws_on_session_cleanup:
1. A registra Card con flow.output = monad-list:json.
2. B descubre a A via find_remote_providers (assert before contains
   a_peer).
3. Cliente local de A hace farewell -> cleanup -> withdraw_outputs.
4. Espera a que la sesion salga del registro + 100ms para que el
   swarm procese el Command.
5. Nueva query desde B: after NO debe contener a_peer.

3 tests verdes en network_discovery.rs (positivo, negativo, withdraw).
18 tests totales en handshake + net.
This commit is contained in:
Sergio
2026-05-09 15:10:30 +00:00
parent fa0ed98880
commit 2e6afd0973
5 changed files with 195 additions and 5 deletions
@@ -220,6 +220,22 @@ pub fn announce_outputs(net: &BrahmanNet, card: &Card) {
}
}
/// Retira los anuncios DHT previos de [`announce_outputs`] para esta
/// `card`. Llamado desde `cleanup` cuando una sesión cierra (Farewell,
/// EOF, error). El record local se borra al instante; copias
/// replicadas en peers remotos expiran por TTL natural de kad.
pub fn withdraw_outputs(net: &BrahmanNet, card: &Card) {
for flow in &card.flow.output {
let key = flow_dht_key(&flow.name, &flow.ty);
debug!(
target: "brahman_handshake::network",
flow = %flow.name,
"withdraw_output → DHT (stop_providing)"
);
net.stop_providing(&key);
}
}
/// Consulta el DHT por peers que han anunciado proveer el flow
/// `(flow_name, type_ref)`. Devuelve la lista resuelta de `PeerId`s.
/// Lista vacía si nadie anuncia, si la query timeout-ea, o si el