removeInlet method
Unsubscribes from a peer, releasing whatever that inlet holds.
Keyed on nodeUId rather than an endpoint id because an endpoint id is
not stable across election on every transport: LSL's is its source_id,
which encodes the node's role. nodeUId is the one identifier that
survives a role change on all of them, and it is what the departure paths
have in hand.
Idempotent — removing an inlet that is not there is not an error.
The default is a no-op, because on a relay transport a stale inlet is
inert: it costs a routing entry that the hub drops anyway when the peer's
socket closes. Transports holding a real per-peer resource — an LSL inlet,
an RTCPeerConnection — must override, or a departed peer leaks until
dispose.
Implementation
@override
Future<void> removeInlet(String nodeUId) async {
final producer = _producerByNodeUId.remove(nodeUId);
if (producer == null) return;
_subscribedProducers.remove(producer);
_slotOwners.removeWhere((_, owner) => owner == nodeUId);
if (_disposed) return;
// Both halves matter. Dropping the producer locally stops delivery even if
// the frame never lands; the frame stops the hub spending bandwidth on it.
connection.unsubscribe(
streamName: config.name,
subscriberEndpointId: endpointId,
producerEndpointIds: [producer],
);
}