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
integrate the event bus, handle protocol update events, make identify emit deltas #659
Conversation
Aside from the flaky tests we have, all seems good, including the new |
I think changing the protocol for this is overkill, if we want to do that, fine, but it should be separate |
Unfortunately this is not backwards compatible, old peers would erase all existing data for the peer because everything is empty except for the delta submessage (which they don’t deserialise). We’d need to put this in a separate protocol ID. |
@whyrusleeping can you think of the benefits of sending full snapshots? Old peers would still need to upgrade to benefit from this logic, so we might as well iterate on the protocol (see my previous comment for keeping backwards compatibility). We’ve been wanting to emit deltas for address changes as well, as these broadcast messages do get expensive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, agree the Delta is worth doing right now.
@raulk so the idea is that we don't send any delta changes to old non-identify push peers? Or that we just send them the big messages and deal with it? |
@whyrusleeping right now protocol changes were not being transmitted in identify push anyway. Protocol changes only travel via delta (peers that actually handle them!). In the future, once we support addr changes in delta, we can fallback to full identify push if the peer doesn't support delta. That fallback is just not relevant now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems pretty straightforward. And i don't see any glaring problems.
Per my comment on the spec, libp2p/specs#176 (comment), I think the new protocol is unnecessary as versioning the protocol would allow us to gracefully handle backwards compatibility support. |
@jacobheun one potential downside is that a id/2.0.0 -> id/1.0.0 interaction would require an extra round trip, and it would block the identification itself. |
Why? We should know the protocol support before we do the push so we're not unnecessarily pushing to peers that don't support the protocol. Identify push should be separate from identify, which would stay at version 1.0.0, so it shouldn't be blocking. The working implementation of this in JS behaves this way. |
@jacobheun if we subsume |
Associated spec update: libp2p/specs#176. |
@raulk shouldn't go already know the supported protocol before pushing updates? For example in js, since the delta/push should only occur for connected peers, we'd have already done the identify handshake to get the peers supported protocols. Prior to sending the updates we should be able to check the supported protocol versions. For peers that only support push 1.0.0, we can do the full send and the delta for 2.0.0. The handshake would only occur once we've decided and executed the appropriate push version. It sounds like the go version is attempting to push updates to connected peers without checking their supported protocols, which would be a lot of unnecessary noise for peers that don't support it. |
@jacobheun we're getting lost in translation here. Indeed, with If I understood correctly, you were proposing to eliminate the extra protocol and subsume deltas into an implicit capability of a hypothetical baseline coarser One problem with that approach is the extra multistream round trip in a critical path, as I described. Also, deltas are relatively decoupled from the baseline protocol, so I don't see any benefit in bundling them together. |
@raulk I'm not talking about changing identify, just push, so this should cause another round trip. I'll use the protocol id's to be explicit. Instead of: Do: This would serve the same purpose as the delta but allow us to fallback to |
Ah, so it’s a matter of semantics. Delta does not replace the entirety of push’s functionality yet (we don’t send deltas for addr changes yet, we send full dump), so semantically this would get confusing, as |
If the goal is to deprecate push in favour of delta, then I'm okay with this, I just wanted to avoid having multiple protocols to perform updates long term. I think deprecating push in the spec update PR would be helpful for clarifying the intent. fwiw, It does feel like an implementation detail/issue is driving the spec change in a specific direction, as the push spec already accounts for partial updates, go just doesn't support that. That may not be the case, but it's something we should be consciences of. Delta will give us finer, diff like, control over the updates we send, so there's a clear improvement there. |
@jacobheun the baseline protocol supports partial updates, but not diffs as you duly note (added/removed sets) |
The tests aren't flaky, they're failing. |
@Stebalien succeeded for me in master locally, see logs. Tests passing on master~/Workbench/protocol/workspace-go-libp2p/go-libp2p master ❯ go test -v ./... === RUN TestNewHost --- PASS: TestNewHost (0.12s) === RUN TestBadTransportConstructor --- PASS: TestBadTransportConstructor (0.00s) === RUN TestNoListenAddrs --- PASS: TestNoListenAddrs (0.32s) === RUN TestNoTransports --- PASS: TestNoTransports (0.52s) === RUN TestInsecure --- PASS: TestInsecure (0.10s) === RUN TestDefaultListenAddrs --- PASS: TestDefaultListenAddrs (0.50s) === RUN TestChainOptions --- PASS: TestChainOptions (0.00s) PASS ok github.com/libp2p/go-libp2p 1.601s === RUN TestNilOption --- PASS: TestNilOption (0.00s) === RUN TestMuxerSimple --- PASS: TestMuxerSimple (0.00s) === RUN TestMuxerByValue --- PASS: TestMuxerByValue (0.00s) === RUN TestMuxerDuplicate --- PASS: TestMuxerDuplicate (0.00s) === RUN TestMuxerError --- PASS: TestMuxerError (0.00s) === RUN TestMuxerBadTypes --- PASS: TestMuxerBadTypes (0.00s) === RUN TestCatchDuplicateTransportsMuxer === RUN TestCatchDuplicateTransportsMuxer/no_duplicate_transports === RUN TestCatchDuplicateTransportsMuxer/duplicate_transports --- PASS: TestCatchDuplicateTransportsMuxer (0.02s) --- PASS: TestCatchDuplicateTransportsMuxer/no_duplicate_transports (0.00s) --- PASS: TestCatchDuplicateTransportsMuxer/duplicate_transports (0.00s) === RUN TestHandleReturnValue --- PASS: TestHandleReturnValue (0.00s) === RUN TestCheckReturnType --- PASS: TestCheckReturnType (0.00s) === RUN TestCallConstructor --- PASS: TestCallConstructor (0.00s) PASS ok github.com/libp2p/go-libp2p/config 0.069s === RUN TestMdnsDiscovery --- SKIP: TestMdnsDiscovery (0.00s) mdns_test.go:25: TestMdnsDiscovery fails randomly with current lib PASS ok github.com/libp2p/go-libp2p/p2p/discovery 0.031s === RUN TestHostSimple --- PASS: TestHostSimple (0.12s) === RUN TestProtocolHandlerEvents --- PASS: TestProtocolHandlerEvents (0.10s) === RUN TestHostAddrsFactory --- PASS: TestHostAddrsFactory (0.09s) === RUN TestHostProtoPreference --- PASS: TestHostProtoPreference (0.09s) === RUN TestHostProtoMismatch --- PASS: TestHostProtoMismatch (0.05s) === RUN TestHostProtoPreknowledge --- PASS: TestHostProtoPreknowledge (0.13s) === RUN TestNewDialOld 22:33:32.835 ERROR swarm2: swarm listener accept error: accept tcp4 127.0.0.1:58696: use of closed network connection swarm_listen.go:79 --- PASS: TestNewDialOld (0.12s) === RUN TestProtoDowngrade --- PASS: TestProtoDowngrade (0.14s) === RUN TestAddrResolution --- PASS: TestAddrResolution (0.13s) PASS ok github.com/libp2p/go-libp2p/p2p/host/basic 1.007s === RUN TestCleanupAddrs --- PASS: TestCleanupAddrs (0.00s) === RUN TestAutoRelay --- PASS: TestAutoRelay (6.47s) PASS 22:33:38.687 ERROR swarm2: swarm listener accept error: accept tcp6 [::]:58710: use of closed network connection swarm_listen.go:79 22:33:38.687 ERROR swarm2: swarm listener accept error: accept tcp4 0.0.0.0:58709: use of closed network connection swarm_listen.go:79 ok github.com/libp2p/go-libp2p/p2p/host/relay 6.514s ? github.com/libp2p/go-libp2p/p2p/host/routed [no test files] === RUN TestNotifications --- FAIL: TestNotifications (0.00s) mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:107: got notif for closed stream mock_notif_test.go:148: 13d4Nv46i /ip6/100::543:c6ec:7c2f/tcp/4242 <--0xc00047a000--> 13fSCvvsD /ip6/100::558:d703:3cec/tcp/4242 mock_notif_test.go:152: 13fSCvvsD /ip6/100::558:d703:3cec/tcp/4242 <--0xc00047a070--> 13d4Nv46i /ip6/100::543:c6ec:7c2f/tcp/4242 mock_notif_test.go:97: got notif for opened stream mock_notif_test.go:102: got incorrect stream 0xc00047a000 0xc00037a230 === RUN TestNetworkSetup --- PASS: TestNetworkSetup (0.02s) === RUN TestStreams --- PASS: TestStreams (0.00s) === RUN TestStreamsStress --- PASS: TestStreamsStress (1.02s) === RUN TestAdding --- PASS: TestAdding (0.04s) === RUN TestRateLimiting --- PASS: TestRateLimiting (0.00s) === RUN TestLimitedStreams --- FAIL: TestLimitedStreams (2.81s) mock_test.go:588: Expected 2ish seconds but got 2.438186423s === RUN TestFuzzManyPeers --- PASS: TestFuzzManyPeers (18.76s) === RUN TestStreamsWithLatency --- PASS: TestStreamsWithLatency (1.51s) FAIL FAIL github.com/libp2p/go-libp2p/p2p/net/mock 24.895s === RUN TestObsAddrSet --- PASS: TestObsAddrSet (0.24s) === RUN TestAddAddrsProfile --- PASS: TestAddAddrsProfile (14.11s) === RUN TestIDService --- PASS: TestIDService (6.21s) id_test.go:62: test peer1 has peer2 addrs correctly id_test.go:79: test peer2 has peer1 addrs correctly id_test.go:62: test peer1 has peer2 addrs correctly id_test.go:79: test peer2 has peer1 addrs correctly id_test.go:62: test peer1 has peer2 addrs correctly id_test.go:79: test peer2 has peer1 addrs correctly === RUN TestProtoMatching --- PASS: TestProtoMatching (0.00s) === RUN TestIdentifyDeltaOnProtocolChange --- PASS: TestIdentifyDeltaOnProtocolChange (1.04s) === RUN TestIdentifyDeltaWhileIdentifyingConn --- PASS: TestIdentifyDeltaWhileIdentifyingConn (1.04s) PASS ok github.com/libp2p/go-libp2p/p2p/protocol/identify 22.668s ? github.com/libp2p/go-libp2p/p2p/protocol/identify/pb [no test files] === RUN TestPing --- PASS: TestPing (0.08s) ping_test.go:48: ping took: 1.073255ms ping_test.go:48: ping took: 134.868µs ping_test.go:48: ping took: 155.948µs ping_test.go:48: ping took: 130.114µs ping_test.go:48: ping took: 130.946µs ping_test.go:48: ping took: 205.699µs ping_test.go:48: ping took: 110.686µs ping_test.go:48: ping took: 119.702µs ping_test.go:48: ping took: 123.491µs ping_test.go:48: ping took: 114.614µs PASS ok github.com/libp2p/go-libp2p/p2p/protocol/ping 0.129s === RUN TestBackpressureStreamHandler --- SKIP: TestBackpressureStreamHandler (0.00s) backpressure_test.go:37: Sadly, as cool as this test is, it doesn't work Because spdystream doesnt handle stream open backpressure well IMO. I'll see about rewriting that part when it becomes a problem. |
^^ EDIT: it's possible what we're seeing is the effect of the race detector limiting goroutines. I also noticed there's a race in the |
I'm seeing several issues:
But yeah, unfortunately these aren't failing reliably. |
This PR introduces the following:
EvtLocalProtocolsUpdated
events when protocol handlers are added and removed.EvtLocalProtocolsUpdated
).EvtPeerProtocolsUpdated
.TODO: