-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat: add libp2p factory config option with example #1470
Conversation
fa7f5d0
to
deab67d
Compare
README.md
Outdated
- `libp2p` (object) add custom modules to the libp2p stack of your node | ||
- `libp2p` (object or function(ipfs, config)) add custom modules to the libp2p stack of your node | ||
|
||
The libp2p option allows you to build your libp2p node by configuration, or via a generator. If you are looking to just modify the below options, using the object format is the quickest way to get the default features of libp2p. If you need to create a more customized libp2p node, such as with custom transports or peer/content routers that need some of the ipfs data on startup, a generator is a great way to achieve this. |
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.
I'm wondering if "generator" might be confused with an actual JS generator function? IMHO it would be more appropriate to call it a factory function.
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.
Yes I agree that could get confusing, I will update the references to factory.
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.
I think this happened but then got changed back?
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.
wow, I spaced on that one. Came back from vacation saw some inconsistencies between factory/generator and changed everything the wrong way. Everything should be factory now, aside from the branch name.
README.md
Outdated
|
||
The libp2p option allows you to build your libp2p node by configuration, or via a generator. If you are looking to just modify the below options, using the object format is the quickest way to get the default features of libp2p. If you need to create a more customized libp2p node, such as with custom transports or peer/content routers that need some of the ipfs data on startup, a generator is a great way to achieve this. | ||
|
||
You can see the generator in action in the [custom libp2p example](examples/custom-libp2p). |
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.
💯 for adding an example too!
examples/custom-libp2p/index.js
Outdated
const libp2pGenerator = (_ipfsNode, _ipfsConfig) => { | ||
// Set convenience variables to clearly showcase some of the useful things that are available | ||
const peerInfo = _ipfsNode._peerInfo | ||
const peerBook = _ipfsNode._peerBook |
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.
hmm, _peerInfo
and _peerBook
presumably are pefixed with underscores because they're considered private APIs - I don't think we should encourage people to use them like this!
Would it be simpler and also still solve the issue (libp2p/js-libp2p#222) to just allow passing peerInfo
and peerBook
to transports in the same way we do for peer discovery modules? https://github.com/libp2p/js-libp2p/blob/master/src/index.js#L185
I see the value in potentially being able to subclass Libp2p
and also passing in the IPFS config, but if we don't have a use case for those two features I'd be tempted to go for a simpler approach for now to directly address @pgte's issue and which is also beneficial to people who use libp2p directly too.
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.
Ah, you might have to ignore that last comment (apologies it's late and I should be asleep already), I just looked at the code being used https://github.com/ipfs-shipyard/peer-star-app/blob/master/src/transport/ipfs.js#L26 and the issue is not being able to use the same instance in both transport
and peerDiscovery
.
Let me re-review this tomorrow.
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.
For _peerInfo
and _peerBook
it would probably be better to create some getter methods for those so it's clearer what users should be doing. What do you think?
For some additional context on another problem with the existing approach that a factory will help easily solve:
I am currently working on peer and content delegation for libp2p. The content delegate needs the peerInfo of the node, but also has options for other parameters, https://github.com/libp2p/js-libp2p-delegated-content-routing/blob/011adc9e90aefe786cc6103fbd3ebb9e007268b7/src/index.js#L41. It's possible that this could be done via the libp2p configuration, but I worry that the configuration is going to get annoyingly complicated for users trying to do anything more complex. As libp2p grows and more modules are introduced or created by users, I think that having more flexibility over the nodes creation is going to be really valuable for users.
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.
Unless you think it's valuable to have these accessible outside of libp2p node creation context I'd probably have these passed separately to the factory function rather than exposing a new public API. I'd rather not have to support people randomly mutating the peer info/book.
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.
I'll update it to pass those into the generator.
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.
I've updated the generator to take a single object argument which includes the peerInfo, peerBook, ipfs node options and ipfs node config. The example has also been updated and I fixed the conflicts with master. Should be ready for another look over.
4ff95d6
to
31b1e61
Compare
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 to me!
a43a1f2
to
585c882
Compare
585c882
to
289b12e
Compare
@jacobheun I've rebased the branch, just waiting for CI |
examples/custom-libp2p/index.js
Outdated
// Now that we have our custom factory, let's start up the ipfs node! | ||
const node = new IPFS({ | ||
libp2p: libp2pFactory | ||
}) |
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.
Instead of calling it Factory, let's just reuse the wording around libp2p bundles (used in https://github.com/libp2p/js-libp2p#creating-your-own-libp2p-bundle, the website, slidedecks and other places).
Also, it would be great that instead of passing a factory, we could pass the libp2p instance itself.
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.
I can switch up the wording to be libp2p bundle compliant.
For passing the libp2p instance, we can't currently do that due to needing the PeerInfo on creation, which is created on ipfs pre-start. When libp2p gets its state machine update we could make creation and startup more flexible so that PeerInfo could be provided to libp2p before it is started and then it could in turn bootstrap (either directly or via event hooks) all of its dependents that require PeerInfo of PeerId data.
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.
I've updated the language to be more bundle centric, and added a link to the example in the main examples readme since it wasn't there yet.
CI green - @diasdavid is it 👍by you 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.
I see a bunch of times that the factory
keyword is used. I understand that is indeed the design pattern. If you feel that the docs are clean enough and not add more unnecessary terms to the language already used in libp2p, then LGTM :)
README.md
Outdated
@@ -301,8 +301,11 @@ Modify the default IPFS node config. This object will be *merged* with the defau | |||
| Type | Default | | |||
|------|---------| | |||
| object | [`libp2p-nodejs.js`](https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/libp2p-nodejs.js) in Node.js, [`libp2p-browser.js`](https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/libp2p-browser.js) in browsers | | |||
| function | [`libp2p factory`](examples/custom-libp2p) | |
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.
Was leaving the word factory
here intentional?
Ah sorry I only looked at the commit with the change - @jacobheun would you mind changing the rest as well? |
Remainder of the factory language has been updated to bundle. |
Resolves #1463 and libp2p/js-libp2p#222
This adds the ability to pass a libp2p generator function to the ipfs configuration. This makes it easier for users to add custom modules to libp2p that require some startup time properties, like peerInfo (libp2p/js-libp2p#222).
I have also included an example of how to do this. I think this makes complex libp2p configuration much cleaner and easier to do.
Tests have been added for the old configuration options and the new generator option. I isolated them to avoid spinning up a full ipfs node.