-
Notifications
You must be signed in to change notification settings - Fork 37
refactor: pass in IPLD Formats into the constructor #164
Conversation
It's not clear, but the parts of the CI that matter passed (and the failed part can't be retriggered). |
|
||
function noop () {} | ||
|
||
class IPLDResolver { | ||
constructor (options) { | ||
constructor (userOptions) { | ||
const options = mergeOptions(IPLDResolver.defaultOptions, userOptions) |
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 should be enough here right ?
const options = mergeOptions(IPLDResolver.defaultOptions, userOptions) | |
const options = Object.assign({}, IPLDResolver.defaultOptions, userOptions) |
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 want a to have a deep copy. Example:
'use strict'
const mergeOptions = require('merge-options')
const oa1 = {main: {sub: 1}}
const oa2 = {main: {sub: 2}}
const oa = Object.assign({}, oa1, oa2)
oa2.main.sub = 3
console.log('oa:', oa)
const mo1 = {main: {sub: 1}}
const mo2 = {main: {sub: 2}}
const mo = mergeOptions(mo1, mo2)
mo2.main.sub = 3
console.log('mo:', mo)
Output is:
oa: { main: { sub: 3 } }
mo: { main: { sub: 2 } }
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Deep_Clone for more information about Object.assign()
.
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.
ok just wanted to make sure we really need deep copy here.
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.
K, cool. I prefer code which doesn't lead to weird surprises in the long run (+ I've coded functional programming language for a looong tim)
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.
@vmx can i suggest https://www.npmjs.com/package/assign-deep instead of merge-options. Check https://codesandbox.io/s/742p0rjvy0, assign-deep is smaller and handles non-plain-objects values better like promises (merge-options gives empty object when you should get a Promise). We should use assign-deep everywhere.
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.
@hugomrdias: I want to have a deep copy, that makes things easier to debug/reason about. assign-deep
does only a shallow copy.
Though I'd love to see that we agree on something decent across all libs.
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 just read ipfs/js-ipfs#1663 (comment). Perhaps it's not always a good idea to copy things. I think I need to put more thought into this. Though I'll merge this for now to keep things going.
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.
LGTM
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.
These PR should be done in tandem to PR to IPLD examples in js-ipfs and also add an example to this repo that shows how to add the multple formats.
@diasdavid I've done the js-ipfs change already locally. Once this change is merged and released. I will make PRs to those repos updating js-ipld with the corresponding changes. There's not point of keep too many PRs open for a long time. |
@vmx we've been working and encouraging on working with Open PRs since the beginning of the project. It helps track work and get others to see and experiment as well. When there is a PR that requires many other PRs, then we link then and make sure that we explain that on the top level PR. |
5546e70
to
ea2bba9
Compare
Codecov Report
@@ Coverage Diff @@
## master #164 +/- ##
=========================================
Coverage ? 89.13%
=========================================
Files ? 1
Lines ? 184
Branches ? 0
=========================================
Hits ? 164
Misses ? 20
Partials ? 0
Continue to review full report at Codecov.
|
Instead of having IPLD using all currently available [IPLD Format] implementations automatically, pass the Formats that should be used into the constructor as options. This will also decrease the bundle size as every user of IPLD can decide which IPLD Formats should be used. By default [ipld-dag-cbor] and [ipld-dag-pb] are used as those are the ones also heavily used within the IPFS ecosystem. BREAKING CHANGE: Not all IPLD Formats are included by default By default only the [ipld-dag-cbor], [ipld-dag-pb] and [raw] [IPLD Format]s are included. If you want to use other IPLD Formats you need to pass them into the constructor. The code to restore the old behaviour could look like this: ```js const ipldBitcoin = require('ipld-bitcoin') const ipldDagCbor = require('ipld-dag-cbor') const ipldDagPb = require('ipld-dag-pb') const ipldEthAccountSnapshot = require('ipld-ethereum').ethAccountSnapshot const ipldEthBlock = require('ipld-ethereum').ethBlock const ipldEthBlockList = require('ipld-ethereum').ethBlockList const ipldEthStateTrie = require('ipld-ethereum').ethStateTrie const ipldEthStorageTrie = require('ipld-ethereum').ethStorageTrie const ipldEthTrie = require('ipld-ethereum').ethTxTrie const ipldEthTx = require('ipld-ethereum').ethTx const ipldGit = require('ipld-git') const ipldRaw = require('ipld-raw') const ipldZcash = require('ipld-zcash') … const ipld = new Ipld({ blockService: blockService, formats: [ ipldBitcoin, ipldDagCbor, ipldDagPb, ipldEthAccountSnapshot, ipldEthBlock, ipldEthBlockList, ipldEthStateTrie, ipldEthStorageTrie, ipldEthTrie, ipldEthTx, ipldGit, ipldRaw, ipldZcash ] }) ``` [ipld-dag-cbor]: https://github.com/ipld/js-ipld-dag-cbor [ipld-dag-pb]: https://github.com/ipld/js-ipld-dag-pb [ipld-raw]: https://github.com/ipld/js-ipld-raw [IPLD Format]: https://github.com/ipld/interface-ipld-format
@diasdavid Projects I've identified that need changes if this change is released:
There is already an example on how to add other formats in the README. |
const {resolver, util} = format | ||
const multicodec = resolver.multicodec | ||
this.support.add(multicodec, resolver, util) | ||
} |
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'll undo the perf work here #145 as IPFS (and potentially others) will have to require these formats upfront.
Can we load these on demand? This would actually be good for IPFS in browsers because we could exclude the implementations from the bundle but add loaders to load in the code when/if needed.
Something like this?:
// In IPFS:
ipld.support.add('git-raw', () => new Promise((resolve, reject) => {
// Could replace with a XHR request. In Node.js we just:
resolve(require('ipld-git'))
}))
// In ipld
let format
if (typeof this.support[codec] === 'function') {
format = await this.support[codec]()
this.support[codec] = format
} else if (this.support[codec]) {
format = this.support[codec]
} else {
throw new Error('missing format')
}
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.
My idea was that you'd normally pass in only the things you need anyway. But then I found out that this is certainly not the case for the js-ifps CLI, where you want support for all formats.
That's a good idea. Thanks for also flushing out the code.
This backwards compatible PR allows missing IPLD formats to be loaded dynamically. This follows on from the discussion here #164 (comment) A new constructor option `loadFormat` allows users to asynchronously load an IPLD format. The IPLD instance will call this function automatically when it is requested to resolve a format that it doesn't currently understand. This can re-enable lazy loading for IPLD modules in IPFS and also means that people who just want to add _more_ resolvers can do so without having to depend directly on the defaults and pass them in as well. License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
This backwards compatible PR allows missing IPLD formats to be loaded dynamically. This follows on from the discussion here #164 (comment) A new constructor option `loadFormat` allows users to asynchronously load an IPLD format. The IPLD instance will call this function automatically when it is requested to resolve a format that it doesn't currently understand. This can re-enable lazy loading for IPLD modules in IPFS and also means that people who just want to add _more_ resolvers can do so without having to depend directly on the defaults and pass them in as well. License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
This PR uses the new `loadFormat` option for IPLD to lazily require IPLD formats in order to reduce the startup time for the node. If you're feeling like you've seen this before then, for reference: The PR ipld/js-ipld#164 undid the work done in ipld/js-ipld#145 and ipld/js-ipld#178 re-enabled lazy loading. License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
This PR uses the new `loadFormat` option for IPLD to lazily require IPLD formats in order to reduce the startup time for the node. If you're feeling like you've seen this before then, for reference: The PR ipld/js-ipld#164 undid the work done in ipld/js-ipld#145 and ipld/js-ipld#178 re-enabled the ability to do so. This PR makes use of this new ability to lazy load the formats. License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
Instead of having IPLD using all currently available IPLD Format
implementations automatically, pass the Formats that should be
used into the constructor as options.
This will also decrease the bundle size as every user of IPLD can
decide which IPLD Formats should be used. By default
ipld-dag-cbor and ipld-dag-pb are used as those are the ones
also heavily used within the IPFS ecosystem.
BREAKING CHANGE: Not all IPLD Formats are included by default
By default only the ipld-dag-cbor and ipld-dag-pb IPLD Formats
are included. If you want to use other IPLD Formats you need
to pass them into the constructor.
The code to restore the old behaviour could look like this:
/cc @alanshaw @hugomrdias