Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

feat: add libp2p factory config option with example #1470

Merged
merged 6 commits into from
Aug 30, 2018

Conversation

jacobheun
Copy link
Contributor

@jacobheun jacobheun commented Jul 26, 2018

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.

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.
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

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).
Copy link
Member

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!

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
Copy link
Member

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor

@pgte pgte left a 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!

@alanshaw alanshaw mentioned this pull request Aug 9, 2018
22 tasks
@jacobheun jacobheun force-pushed the feat/libp2p-generator branch 3 times, most recently from a43a1f2 to 585c882 Compare August 16, 2018 17:37
@jacobheun jacobheun changed the title feat: add libp2p generator config option with example feat: add libp2p factory config option with example Aug 16, 2018
@alanshaw
Copy link
Member

@jacobheun I've rebased the branch, just waiting for CI

// Now that we have our custom factory, let's start up the ipfs node!
const node = new IPFS({
libp2p: libp2pFactory
})
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@alanshaw
Copy link
Member

CI green - @diasdavid is it 👍by you now?

Copy link
Member

@daviddias daviddias left a 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) |
Copy link
Member

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?

@alanshaw
Copy link
Member

Ah sorry I only looked at the commit with the change - @jacobheun would you mind changing the rest as well?

@jacobheun
Copy link
Contributor Author

Remainder of the factory language has been updated to bundle.

@alanshaw alanshaw merged commit 46222e1 into master Aug 30, 2018
@ghost ghost removed the status/in-progress In progress label Aug 30, 2018
@alanshaw alanshaw deleted the feat/libp2p-generator branch August 30, 2018 07:23
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants