Repository navigation
refactor: API changes and switch to async iterators - #29
Conversation
|
@jacobheun @alanshaw @dirkmc can I have your opinion on this proposal? Meanwhile, I will be working on adding a suite of tests and a draft PR for one of the repos using this Interface |
dirkmc
left a comment
There was a problem hiding this comment.
Thanks for putting this together @vasco-santos
I just made a couple of small suggestions.
7d6d51d to
5ece693
Compare
|
I have been thinking about the interface's current implementation and there are several things that do not make sense to me. Moreover, as we have an ongoing effort for the libp2p introspection, there is a lot of data missing in According to the In the interface connection from the go implementation, it is provided a way to open streams and it stores the streams associated with the connection. Afterward, there is also an interface for streams, which is in reality what we were trying to achieve here. I have discussed this with @jacobheun and we agreed that being able to implement an echo protocol as follows, would be a big improvement: // An echo protocol
const echo = (stream) => { /* Runs the protocol over this stream */ }
// A new connection and echo
const connection = await libp2p.connect(peerInfo)
const stream = connection.newStream()
await echo(stream)
// An existing connection
const connection = await libp2p.getConnection(peerInfo)
const stream = connection.newStream()
await echo(stream)In this context, I created a draft for the |
5ece693 to
291eab5
Compare
|
Updated this PR with my new proposal. I will work on a PR on top of libp2p/js-libp2p-tcp#102 to integrate this and see how it goes. Meanwhile, I would like some feedback |
dirkmc
left a comment
There was a problem hiding this comment.
This looks like a big step in the right direction, thanks for putting this together @vasco-santos 🎉
f32d597 to
355e036
Compare
|
The problem that I described during the JS Core Sync call was basically the distinction between a socket in the "connection" created and the For example, in libp2p/js-libp2p-tcp#102 we have the following codebase: class TCP {
async dial (ma, options) {
const cOpts = ma.toOptions()
const rawSocket = await this._connect(cOpts, options)
return new Libp2pSocket(rawSocket, ma, options)
}
}The My main concern was regarding the representation of this Stating what I just added to the Readme: ConnectionBefore creating a connection from a transport compatible with
A connection stands for the libp2p communication duplex layer between two nodes. It is not the underlying raw transport duplex layer (socket), such as a TCP socket, but an abstracted duplex layer that sits on top of the raw socket. When a libp2p transport creates its socket, a new The transport must handle the translation of cleanup from the socket to the connection. That is, the errors, resets or closes on the socket must be passed to the connection. In the same way, the transport must map these actions from the const pipe = require('it-pipe')
const { Connection } = require('interface-connection')
class Transport {
async dial () {
// ...
// create the raw socket and the connection
const socket = await this._connect()
const conn = new Connection(remotePeerInfo, remoteMa)
// pipe the socket through the connection (if necessary include a conversion to iterable duplex streams)
pipe(socket, conn, socket)
// bind the necessary handlers to update state changes (error, close, reset, ...)
// ...
return conn
}
_connect () {}
}Let me know what you guys think |
eacfaef to
c7299d1
Compare
|
Very nice explanation, I like it a lot 👍 |
60277b1 to
1107d54
Compare
|
I made a few changes on the approach. Basically, if we want to go with the pipe approach, we need to have the I changed the approach for the transports to extend the connection using their raw socket as follows: const abortable = require('abortable-iterator')
const { Connection } = require('interface-connection')
class Libp2pSocket extends Connection {
constructor (rawSocket, ma, opts = {}) {
super(ma, opts)
this._rawSocket = rawSocket
this.sink = this._sink(opts)
this.source = opts.signal ? abortable(rawSocket.source, opts.signal) : rawSocket.source
}
_sink (opts) {
return async (source) => {
try {
await this._rawSocket.sink(abortable(source, opts.signal))
} catch (err) {
// Re-throw non-aborted errors
if (err.type !== 'aborted') throw err
// Otherwise, this is fine...
await this._rawSocket.close()
}
}
}
}
module.exports = Libp2pSocketconst Libp2pSocket = require('./socket')
class Transport {
async dial () {
// ...
// create the raw socket and the connection
const socket = await this._connect()
const conn = new libp2pSocket(socket, remoteMa, {})
return conn
}
_connect () {}
}I got inspiration on the libp2p/js-libp2p-tcp#109 There are some tests failing. The majority is related to the adapter tests for I think that this approach is cleaner and more appropriate to the transport implementation. This approach also helps ensuring that the transport is responsible for socket management, while also allowing the application layer to handle the connection management. Let me know your thoughts |
|
This does seem like a better approach to me 👍 |
|
I think the thing we just need to do for this to get to a final decisions is to actually exchange data over a muxed connection with this, the async tcp transport, and the mplex iterator. It will force us to make sure the mplex async version is done and we'll catch usability issues for this. i think it's going to be hard to nail down a version until that's done. That or we may make big changes to this after the fact. |
|
I agree! I will work on that experiment and let you know! |
Co-Authored-By: Alan Shaw <alan.shaw@protocol.ai>
Co-Authored-By: Alan Shaw <alan.shaw@protocol.ai>
fix: resolve bugs from using tests
00bdeb7 to
7164204
Compare
f4828f8 to
c7a62f3
Compare
199be5d to
65372c0
Compare
65372c0 to
6f920a6
Compare
jacobheun
left a comment
There was a problem hiding this comment.
Some minor things after the latest changes. I'm leveraging this in the latest version of the switch dial flow I am working on and everything is looking pretty good. After this round I think this should be good to merge and we can do any additional changes in followup PRs.
b31bd23 to
21c2ebd
Compare
Co-Authored-By: Jacob Heun <jacobheun@gmail.com>
21c2ebd to
15f000c
Compare
jacobheun
left a comment
There was a problem hiding this comment.
This looks good! Let's merge this monster!
BREAKING CHANGE: all the callbacks in the provided API were removed and each function uses aync/await
Needs:
Closes #2 #26 #28