-
Notifications
You must be signed in to change notification settings - Fork 20
feat: update DAGLink and DAGNode to have an immutable API #6
Conversation
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 it would be good to keep a toJSON
method, to make it more consistent rather than a property .json
. For both node and link
get () { | ||
return data | ||
}, | ||
set: immutableError |
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.
You can make this nicer as you are already using class
class Hello {
get myImmutableProp () {
return this._secretProp
}
set myImmutableProp () {
throw new Error('fail')
}
}
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.
well, that is what I did, but defined the function above so that I could reuse it
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.
right, nevermind, I got what you meant now :) and agreed 👍
Name: this.name, | ||
Size: this.size, | ||
Hash: mh.toB58String(this.hash) | ||
this.json = { |
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 defined as immutable as the props in DagNode
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.
agreed 👍
I tend to agree, will update |
I have quite a few comments for this, but can't review it atm. Will get back to this asap. |
// 3. create new node | ||
} | ||
} | ||
callback(new Error('invalid arguments')) |
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.
…lder, make tests pass again
… write more tests
8f7aadc
to
f53e0c8
Compare
All right, this is ready to be reviewed so that I can go forward and bubble up updates across the other repos. Big wins from this PR:
@haadcode @dignifiedquire @victorbjelkholm would like a final 👍 so that I can move forward. Thank you! |
exports.DAGLink = require('./dag-link.js') | ||
exports.resolver = require('./resolver.js') | ||
exports.util = require('./util.js') | ||
exports.DAGNode = require('./dag-node') |
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 will make const d = new DAGNode() possible for users. I thought we didn't want that to be exposed directly so that users are forced to user .create and have no confusion as to how to create DAGNodes.
exports.resolver = require('./resolver.js') | ||
exports.util = require('./util.js') | ||
exports.DAGNode = require('./dag-node') | ||
exports.DAGLink = require('./dag-link') | ||
|
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.
Same as above, this will expose DAGLink to the consumers.
const dagNode = new DAGNode(buf, links) | ||
|
||
callback(null, dagNode) | ||
DAGNode.create(buf, links, callback) |
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.
@diasdavid we talked about the IPLD format API and this is pretty much what I meant how it forces sub-optimal code: deserialize depends on DAGNode and DAGNode depends on serialize (serialize and deserialize being both in the same file) essentially creating a cyclic dependency between the two. For the sake of getting this shipped, let's not focus on that but keep this in mind for future discussions.
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.
We could break util into separate files for each function, avoiding that 'cyclic' dependency, do note that in CJS, modules loaded are cached, solving this potential issue without any intervention.
Nevertheless, this is not a IPLD Format issue, if an issue at all, is just because we want the DAGNode instances to be immutable and easy to work with and so, we need the serialize version upon its creation.
Couple of small comments, otherwise LGTM! |
Create a DAGNode. | ||
|
||
```JavaScript | ||
DAGNode.create("data", links, (err, dagNode) => { |
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.
quotes
#### Create a DAGNode | ||
|
||
```JavaScript | ||
// TODO |
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.
TODO: please fill or remove before merge
#### Add and remove a Link | ||
|
||
```JavaScript | ||
// TODO |
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.
TODO: please fill or remove before merge
const DAGNode = dagPB.DAGNode | ||
``` | ||
|
||
#### DAGNode.create(data, links, hashAlg, callback) |
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.
Please document the argument types
} | ||
``` | ||
|
||
#### addLink(node, link, callback) |
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.
Please document the argument types
} | ||
|
||
return new DAGLink(l.name || l.Name, | ||
l.size || l.Size, |
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.
indentation is off
} | ||
|
||
return 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.
this can be simplified to
function cloneData (dagNode) {
assert(Buffer.isBuffer(dagNode.data), 'Not a valid dagnode')
const data = new Buffer(dagNode.data.length)
dagNode.data.copy(data)
return data
}
} | ||
|
||
function cloneLinks (dagNode) { | ||
return dagNode.links.length > 0 ? dagNode.links.slice() : [] |
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.
no need for the length check, [].slice() === []
} | ||
|
||
function linkSort (a, b) { | ||
return (new Buffer(a.name || '', 'ascii').compare(new Buffer(b.name || '', 'ascii'))) |
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 is super wasteful, the link names should be converted to buffers once and then sorted, not on every sorting call.
} | ||
|
||
exports.serialize = serialize | ||
exports.deserialize = deserialize | ||
exports.cid = cid |
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.
👎 on the whole util
interface, it seems arbitrary and not very useful. If these methods are needed why are they not exposed at the top level?
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.
@dignifiedquire go through https://github.com/ipld/interface-ipld-format and ipld/js-ipld#60 (comment)
tl;dr; it is what the IPLD Resolver needs and what was defined on interface-ipld-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.
okay :/
b3b9385
to
2b1a356
Compare
@dignifiedquire @victorbjelkholm @haadcode did a push on this so that we can get this final API stable, while the API for IPLD Formats are still hot, I'm afraid that if we give it a lot more time, people will start using all of that async ugliness because of the lack of immutability here and then it becomes harder to change.
I'm finishing this up, but API is there, would love your review ASAP
note: This PR also cuts the umbilical chord to the merkleDAG version in Go, which created a funky api in JS