Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

feat: new IPLD Format API #51

Closed
wants to merge 4 commits into from
Closed

feat: new IPLD Format API #51

wants to merge 4 commits into from

Conversation

vmx
Copy link
Member

@vmx vmx commented Apr 21, 2019

BREAKING CHANGE: The API is now async/await based

There are numerous changes, the most significant one is that the API
is no longer callback based, but it using async/await.

For the full new API please see the IPLD Formats spec.

BREAKING CHANGE: The API is now async/await based

There are numerous changes, the most significant one is that the API
is no longer callback based, but it using async/await.

For the full new API please see the [IPLD Formats spec].

[IPLD Formats spec]: https://github.com/ipld/interface-ipld-format
@ghost ghost assigned vmx Apr 21, 2019
@ghost ghost added the status/in-progress In progress label Apr 21, 2019
@codecov
Copy link

codecov bot commented Apr 21, 2019

Codecov Report

Merging #51 into master will increase coverage by 2.52%.
The diff coverage is 99.21%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #51      +/-   ##
==========================================
+ Coverage   96.84%   99.37%   +2.52%     
==========================================
  Files          22       20       -2     
  Lines         792      635     -157     
==========================================
- Hits          767      631     -136     
+ Misses         25        4      -21
Impacted Files Coverage Δ
eth-state-trie/index.js 100% <100%> (ø) ⬆️
util/visibility.js 100% <100%> (ø)
eth-tx/index.js 100% <100%> (ø) ⬆️
eth-state-trie/test/resolver.spec.js 100% <100%> (+11.5%) ⬆️
eth-block/index.js 100% <100%> (ø) ⬆️
eth-tx-trie/index.js 100% <100%> (ø) ⬆️
util/createUtil.js 100% <100%> (ø) ⬆️
eth-storage-trie/test/resolver.spec.js 100% <100%> (+1.42%) ⬆️
eth-storage-trie/index.js 100% <100%> (ø) ⬆️
eth-block/test/resolver.spec.js 100% <100%> (+0.78%) ⬆️
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4eaa791...39fc56f. Read the comment docs.

Copy link
Member

@rvagg rvagg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all a bit too complex for me to give an explicit "Approve" to, I just don't understand the breadth of it so I'll leave it up to you. But here are my two general concerns:

  1. I think the heavy use of Object.defineProperty is risky, and I've pointed to some problems I see already with the eth-account-snapshot stuff. If all of these Eth* objects are predictable in shape, maybe we should just be exposing new plain objects with copies of the data (or getters if the data is expensive to generate). Taking the raw objects and adjusting the properties is pretty messy. The original path-collection process seems a little safer, although probably unoptimal.
  2. I'd remove all uses of new Promise(), it's a good code smell indicator. promisify() is going to fix all of the instances in here in various ways; in fact, you're really just reinventing a simplistic promisify() in most cases.

value: account.isEmpty()
})
const values = {
isEmpty: function () { return this.isEmpty() },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These don't look right, this is going to be the object they are attached to so this.isEmpty() should result in a recursive call. It's set as a 'value' but it's just a function, so I think you're replacing the existing EthAccount#isEmpty() with a new recursive one. What's the intent here?

'codeHash',
'nonce',
'balance',
'isEmpty',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be a big deal to have resolve() calls for each of these to properly sanity check? I suspect we'll find these two is*() calls resolve to functions.

cb(null, cid)
function populateTrie (trie) {
return new Promise((resolve, reject) => {
async.series([
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could just let put = promisify(trie.put.bind(trie)) and then await put(...) of these calls, then async can be removed as a dependency

return array.indexOf(item) !== -1
function dumpTrieNonInlineNodes (trie, fullNodes) {
return new Promise((resolve) => {
trie._findDbNodes((nodeRef, node, key, next) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be promisified too, especially if the callback can return an error, in which case it's going to get turned into a return value via resolve

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no clue how to promisify this one. Can you help?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does _findDbNodes() resolve to something useful here or is the only purpose here to add the nodes to fullNodes?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regardless, I think it would be:

return promisify((...args) => trie._findDbNodes(...args))((n, node, k, next) => {
   fullNodes.push(node)
   next()
})

Or, more readably:

let _find = promisify((...args) => trie._findDbNodes(...args))
let _iter = (n, node, k, next) => {
   fullNodes.push(node)
   next()
}
return _find(_iter)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, to be more consistent with Rod’s earlier recommendation, you’d use promisify(trie._findDbNodes.bind(trie)) instead of promisify((...args) => trie._findDbNodes(...args)).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try this and see if it still works.

function dumpTrieNonInlineNodes (trie, fullNodes) {
  return new Promise((resolve, reject) => {
    trie._findDbNodes((nodeRef, node, key, next) => {
      fullNodes[nibbleToPath(key)] = node
      next()
    }, err => { if (err) return reject(err); resolve() })
  })
}

If it fails with that, then the reason it was succeeding is because you were swallowing the error.

If this still works then let’s just move on because we’ve handled the primary concern and it’s not like we’re worried about the perf benefits of promisify since this is just a test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works, not with promisify though ;) Thanks!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very strange, they should do the same thing, but I’m not that surprised that an API that is using a one-off continuation passing function inside a function that’s a parameter to a standard callback is behaving oddly ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, sounds messy, forget my pickiness then and just make it work

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries. In the other case promisify-ing it really made sense. I found it interesting to see that there are cases where strange callback-based APIs can't easily be promisified.

// context
const createCustomEthTrieNode = function (codec, leafResolver) {
return function (serialized) {
const rawNode = rlp.decode(serialized)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this block needs to be indented by another space

@vmx vmx mentioned this pull request May 6, 2019
@vmx
Copy link
Member Author

vmx commented May 8, 2019

Closing this one in favour of #52.

@vmx vmx closed this May 8, 2019
@ghost ghost removed the status/in-progress In progress label May 8, 2019
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.

3 participants