-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Feature request: Allow extending libp2p.transports/libp2p.discovery instead of overriding it via flag #2579
Comments
I had to override entire js-libp2p bundle used in Brave's js-ipfs just to add TCP transport. |
I'm going to implement this in my current PR |
Would it be better to pass the const ipfs = await IPFS.create({
libp2p: ({ defaultOptions, peerInfo }) => {
defaultOptions.transports.push(...)
return new Libp2p(defaultOptions)
}
}) |
While it does make sense in this use-case, I don't know if we should make |
I think we should keep this very simple and @alanshaw is on the right track. Right now, if I want to add something before passing config to js-libp2p, I need to override entire What if we make a simple change and run custom function creating bundle against defaults from src/core/components/libp2p.js#L136 instead? Something like this (in /src/core/components/libp2p.js): module.exports = function libp2p (self, config) {
const options = self._options || {}
config = config || {}
- // Always create libp2p via a bundle function
- const createBundle = typeof options.libp2p === 'function'
- ? options.libp2p
- : defaultBundle
-
const { datastore } = self._repo
const peerInfo = self._peerInfo
const peerBook = self._peerInfoBook
- const libp2p = createBundle({ options, config, datastore, peerInfo, peerBook })
+ const libp2p = defaultBundle({ options, config, datastore, peerInfo, peerBook }) and later at the end of + let customBundle
+ if (typeof options.libp2p === 'function') {
+ customBundle = options.libp2p
+ delete options.libp2p
+ }
+
const libp2pOptions = mergeOptions(libp2pDefaults, get(options, 'libp2p', {}))
+ if (customBundle) {
+ return customBundle({ libp2pOptions, config, datastore, peerInfo, peerBook })
+ }
// Required inline to reduce startup time
// Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified
const Node = require('../runtime/libp2p-nodejs')
return new Node(libp2pOptions) This way PS. I like the idea of having "drop-in" wrappers like libp2p: ({ datastore, peerInfo, peerBook, options, config }) => {
options = require('stardust4ipfs')(options, config, peerInfo)
options = require('brave4ipfs')(options, config, peerInfo, datastore, peerBook)
return new Libp2p(options)
} We could add some sugar that enables us to run them sequentially to update config with the most common options: libp2p: [require('stardust4ipfs'), require('brave4ipfs')] |
👍
We should instead possibly pass the whole object as-is instead of splitting it up, so you can just directly do We should maybe not do This would also help enabling the |
Returning an instance allows you to subclass Libp2p. Please can we just do the simpliest thing and pass the libp2p options to the bundle function so you can extend/replace (like I suggested in #2579 (comment) and as @lidel fleshed out in #2579 (comment))? |
So, I've created something that allows multiple methods of overriding the libp2p bundle
All of those can be chained, so one can do {
libp2p: [ // any of those is optional
require('stardust4ipfs'),
require('brave4ipfs'),
{extend: true, transports: [MyCustomTransport]},
({options: {libp2p}}) => new Libp2p(libp2p)
]
} If none of the Functions returns libp2p instance, then the default Node from |
It's pushed in #2578 |
{
libp2p: [ // any of those is optional
require('stardust4ipfs'),
require('brave4ipfs'),
{extend: true, transports: [MyCustomTransport]},
({options: {libp2p}}) => new Libp2p(libp2p)
]
} I get it, but this is too complicated. I really want to get the stardust change in but it should be a small focused change. If we're going to allow configuration like this then we should support it more generally for all the options in the constructor (which is a bigger proposal/change and separate PR and discussion). If you want this convenience right now you can easily create a module that accepts this array and spits out an |
Ok. So I'll just do the array function in the curent PR and make another PR with the more complex example later? |
The problem I see with @lidel's solution is that while customBundle gets passed the options for the runtime, the actual transports are mixed in inside the runtime not defaultBundle. The problem with that is, that we only get access to the result of defaultBundle and not the runtime. The current solution in the PR adds the The only solutions, aside from the By internally chaining functions that take a config and return a config and doing This would actually be less complex then my current
Should I implement that instead? |
I believe we should not add any additional toggles such as This sounds better:
We could simplify this furthr and make functions take and return the same "runtime" object as one passed to const runtime = { options, config, datastore, peerInfo, peerBook } Then, we could create "config pipelines" that apply funcitons like {
libp2p: [
(runtime) => stardust4ipfs(runtime), // returns updated runtime2 (passed to the next one)
(runtime2) => brave4ipfs(runtime2), // returns updated runtime3
(runtime3) => new CustomLibp2p(runtime3.options) // optional (implicit call with regular Libp2p if omitted from pipeline)
]
} If subclassing of {
libp2p: [
require('stardust4ipfs')
require('brave4ipfs')
]
} |
The problem here is still, that the runtime is mixing in transports on it's own. As long as we use What if, instead, we mix in the transports in the config pipelines. So we'd have something like this: {
libp2p: [ // all are functions (runtime) => newRuntime
IPFS.libp2p.defaultOptions, // pubsub, delegates (defaultBundle)
IPFS.libp2p.platformOptions, // transports (TCP for node, WS for browser, etc),
require('stardust4ipfs'),
require('brave4ipfs')
] // the resulting runtime.options will be passed to vanilla `Libp2p` class
} This would save us the "runtime-layer" which is causing the trouble with overriding the transports array. (The (The |
@mkg20001 Hot sure if this is helpful, but I took API proposed by @alanshaw in #2591 and used it for customizing transports of JS-IPFS in Brave – see my PR draft at ipfs/ipfs-companion#811. It is bit simpler, instead of globals you change Feels "good enough". |
Type: feature
Severity: low
Description: Feature request: Allow extending libp2p.transports/libp2p.discovery instead of overriding it via flag
It would be good if there would be a flag to add custom transports in addition to the defaults, instead of fully overriding them.
This flag could be named
libp2p.extendOnly
orlibp2p.extends
The text was updated successfully, but these errors were encountered: