-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(iroh): Gossip client #2258
Conversation
I think it is safe to just ignore any messages that are not for us. See b88398e Obviously you can mess with things by subscribing to a namespace that is currently being synced, but doing so accidentally is highly unlikely. And you can also mess with other stuff by using the low level blobs api, so 🤷 . |
It seems that due to the fact that the rpc protocol is public, we can not ever do an additional rpc request without breaking compat.
|
we need to mark the rpc enums as non exhaustive, that should solve this |
longterm I wish the rpc types where all private anyway |
@Frando can we change this? seems unfortunate to subscribe to everything by default |
I think we can, yes. What is our primitive of choice these days to merge a changing list of streams? with futures and thus its merge combinators phased out in iroh - maybe https://docs.rs/futures-concurrency/latest/futures_concurrency/stream/trait.Merge.html ? |
I did not yet give the new gossip dispatcher module a real review, but my first thought is: What about we move the |
#2265 changes the sync engine usage of gossip to not use subscribe_all (based on this branch). |
@Frando so the basic idea of the gossip dispatcher is just to have a thing that wraps the gossip and does some management so that it is less fragile to use. It does the join/unjoin etc. for you and deals with laggy subscribers. If you agree with / can live with the public interface (which is just the subscribe function), we could move something with that signature into iroh-gossip as a higher level interface and then I would use it here, and you could update docs to use it (or not...). The interface is basically this: pub fn subscribe(
&self,
msg: GossipSubscribeRequest,
updates: UpdateStream,
) -> impl Stream<Item = RpcResult<GossipSubscribeResponse>> { where UpdateStream is just a stream of either broadcast or broadcast_neighbours: /// Send a gossip message
#[derive(Serialize, Deserialize, Debug)]
pub enum GossipSubscribeUpdate {
/// Broadcast a message to all nodes in the swarm
Broadcast(Bytes),
/// Broadcast a message to all direct neighbors
BroadcastNeighbors(Bytes),
} There is a hardcoded constant somewhere about how much you are allowed to lag before you are thrown out. We could make that configurable as well. |
I think the API is fine. And still very much in favor of having only one and not 2 high level dispatch interfaces to gossip. |
Ok, I will clean up the dispatcher a bit and make sure it is independent of the rpc protocol, in preparation for moving it into iroh-gossip. |
Moved the dispatcher to iroh-gossip and moved the types into the dispatcher file. I reexported some of the dispatcher types instead of making newtypes for them in the rpc protocol. Not 100% sure about this, but making so many single element newtypes is a drag... One question is if the dispatcher should present a simplified interface for creation. Currently it takes a Gossip. But I don't really see how this can be made really nice. Take an endpoint and an options object? |
# Conflicts: # Cargo.lock # iroh-docs/src/engine/gossip.rs # iroh-gossip/Cargo.toml # iroh/src/client.rs # iroh/src/node.rs # iroh/src/node/builder.rs # iroh/src/rpc_protocol.rs
This is missing adapting the docs stuff to the new gossip dispatcher. Other than that I think it is good to go. |
- connect two nodes - send a message from node 1 - recv it on node 2
otherwise it is impossible to write certain tests using just the client.
impl deref for backwards compat (maybe we can remove this at some point)
# Conflicts: # iroh/src/client.rs
this test is not meant to be a discovery test...
# Conflicts: # iroh/src/client.rs
@Frando I have added a test. It seems to work, now that I have added the ability to tell the endpoint about node addrs (see #2433 ). I think this kind of test is nice, because it forces us to make the client API sufficiently rich that you can do tests with it. Also it is much less likely to fluke out than a full cli type tests. But - do you think this test for gossip will reliably work? I am connecting two nodes and then send a msg from one to the next. Can there be a situation where I send the message too early and it gets lost? |
# Conflicts: # Cargo.lock # iroh/src/node/rpc.rs # iroh/src/rpc_protocol.rs
Yes, Gossip::join is awaited here, and that waits for at least one neighbor to come up before completing. So the remaining TODO is to merge the two dispatchers (in dispatcher.rs and net.rs) so that messages flow only over a single channel and not two. We should do this, but IMO it can also happen in a followup. |
…opic (#2570) ## Description This PR changes the main public `iroh_gossip` to keep track of client-side gossip subscriptions. The `net::Gossip` struct now keeps track of client-side subscribers per topic, which are made up of a pair of two streams/channels: from the client to the actor a stream of updates (outgoing messages) and from the actor to the client a stream of events (incoming messages). Once all client streams&sinks for a topic are dropped, the topic is being quit. This builds on the client API added in #2258, but completely removes the `dispatcher` module, integrating its features directly into the gossip actor. See below for a short list of the API changes. The new API can be browsed [here](https://n0-computer.github.io/iroh/pr/2570/docs/iroh/gossip/net/index.html). The refactor turned out bigger than initially intended, sorry for that, but I did not see a good way to reduce the scope. What's still missing (can also be follow-ups)?: - [ ] Review the new public API - [ ] Align the client API to the iroh_gossip API. The `GossipTopic` can be made to work on both the client and the native API, as it only deals with streams and sinks. ## Breaking Changes * `iroh_gossip::dispatcher` is removed with everything that was in it. use the new API from `iroh_gossip::net::Gossip` instead (see below). * `iroh_gossip::net::Gossip` methods changed: * changed: `join` now returns a `GossipTopic` * removed: `broadcast`, `broadcast_neighbors`, `subscribe`, `subscribe_all`, `quit`. * for `subscribe` use `join` instead, which returns a `GossipTopic` * for `broadcast` and `broadcast_neighbors` use the respective methods on `GossipTopic` . * `quit` is obsolete now, the topic will be quitted once all `GossipTopic` handles are dropped. * `subscribe_all` is no longer available * `iroh_gossip::net::JoinTopicFut` is removed (is now obsolete) ## Notes & open questions <!-- Any notes, remarks or open questions you have to make about the PR. --> ## Change checklist - [x] Self-review. - [x] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [ ] Tests if relevant. - [ ] All breaking changes documented.
…and use ref-cast to eliminate them entirely (#2350) ## Description With 4 different clients, the current approach might be OK. But we are going to have more. E.g. gossip, see n0-computer/iroh#2258 . And in any case it feels weird to store the same thing multiple times. So this replaces public fields in the iroh client with accessors and use ref-cast to eliminate them entirely. There is now only one rpc field, and you can switch from that to the different subsystem client views without runtime overhead, not even an arc clone. ## Breaking Changes Everything that uses the iroh client will have to switch from field accesses to accessor fns. ## Notes & open questions <!-- Any notes, remarks or open questions you have to make about the PR. --> ## Change checklist - [ ] Self-review. - [ ] Documentation updates if relevant. - [ ] Tests if relevant. - [ ] All breaking changes documented.
## Description This makes gossip available in iroh. Using iroh-gossip directly, while not horrible, is a bit verbose. ## Breaking Changes ~~Not sure. It exports a few more things, and adds things. But in theory it should not modify existing things.~~ There should be none, and the semver test seems to agree... ## Notes & open questions - ~~There can be some scenarios where this can cause trouble. E.g. when subscribing and then unsubscribing to a topic that is also used for doc sync.~~ This ^ is taken care of, since docs no longer use subscribe_all! How to deal with missed messages due to slow reader: I think that relying on guaranteed delivery for gossip is not a good idea in any case. so maybe just sending a Lagged but then continuing is best? Forcing the client to resubscribe could be a bit annoying. ## Change checklist - [x] Self-review. - [x] Documentation updates if relevant. - [x] Tests if relevant. - [x] All breaking changes documented.
…opic (#2570) ## Description This PR changes the main public `iroh_gossip` to keep track of client-side gossip subscriptions. The `net::Gossip` struct now keeps track of client-side subscribers per topic, which are made up of a pair of two streams/channels: from the client to the actor a stream of updates (outgoing messages) and from the actor to the client a stream of events (incoming messages). Once all client streams&sinks for a topic are dropped, the topic is being quit. This builds on the client API added in #2258, but completely removes the `dispatcher` module, integrating its features directly into the gossip actor. See below for a short list of the API changes. The new API can be browsed [here](https://n0-computer.github.io/iroh/pr/2570/docs/iroh/gossip/net/index.html). The refactor turned out bigger than initially intended, sorry for that, but I did not see a good way to reduce the scope. What's still missing (can also be follow-ups)?: - [ ] Review the new public API - [ ] Align the client API to the iroh_gossip API. The `GossipTopic` can be made to work on both the client and the native API, as it only deals with streams and sinks. ## Breaking Changes * `iroh_gossip::dispatcher` is removed with everything that was in it. use the new API from `iroh_gossip::net::Gossip` instead (see below). * `iroh_gossip::net::Gossip` methods changed: * changed: `join` now returns a `GossipTopic` * removed: `broadcast`, `broadcast_neighbors`, `subscribe`, `subscribe_all`, `quit`. * for `subscribe` use `join` instead, which returns a `GossipTopic` * for `broadcast` and `broadcast_neighbors` use the respective methods on `GossipTopic` . * `quit` is obsolete now, the topic will be quitted once all `GossipTopic` handles are dropped. * `subscribe_all` is no longer available * `iroh_gossip::net::JoinTopicFut` is removed (is now obsolete) ## Notes & open questions <!-- Any notes, remarks or open questions you have to make about the PR. --> ## Change checklist - [x] Self-review. - [x] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [ ] Tests if relevant. - [ ] All breaking changes documented.
Description
This makes gossip available in iroh. Using iroh-gossip directly, while not horrible, is a bit verbose.
Breaking Changes
Not sure. It exports a few more things, and adds things. But in theory it should not modify existing things.There should be none, and the semver test seems to agree...
Notes & open questions
There can be some scenarios where this can cause trouble. E.g. when subscribing and then unsubscribing to a topic that is also used for doc sync.This ^ is taken care of, since docs no longer use subscribe_all!
How to deal with missed messages due to slow reader:
I think that relying on guaranteed delivery for gossip is not a good idea in any case. so maybe just sending a Lagged but then continuing is best? Forcing the client to resubscribe could be a bit annoying.
Change checklist