-
-
Notifications
You must be signed in to change notification settings - Fork 55
Custom verification function for Log entries #123
Conversation
Updated with a test and docs. I noticed the replication test is failing for me even without my edits |
Thank you @fazo96 for the PR! Looks great and sounds like all tests are passing as expected. I quickly ran the tests yesterday against OrbitDB and they're all green. Will try to give some feedback on the code later this week but by the quick looks, it's fine. |
src/log.js
Outdated
* | ||
* @memberof Log | ||
*/ | ||
set customVerificationFunction (verifyEntry) { |
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.
Let's pass in the verify function through constructor options as we do with other "dependencies"? This way the user doesn't need to do log.customVerificationFunction = () ...
afterwards. I feel that's an easier (safer?) way to do it. What do you think?
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.
Good idea, but then if the log is part of a store how do you pass the custom verification function? Maybe we should let users pass it both through the setter and the constructor. Or we can pass it through the options when store/db is created and have it passed down to the log
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 feel we should do the latter, ie. pass it to Store and then have Store pass it to the log.
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 tried adding a constructor argument, but in the tests for examples many Logs are created using Log.fromEntry or other factory functions like that.
I'm not sure what the best approach is, do you think we should add this option to every factory function? I ended up keeping the setter as well as the constructor argument for now.
I also noticed there was some weird jsdoc syntax before the constructor, I changed it, let me know if that works
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.
@haadcode ping
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.
Hey sorry for the delay!
You're absolutely right, we need to add the verification function passing to the factory functions too in order to make this work. Fortunately it's only three places (afaict):
- https://github.com/orbitdb/ipfs-log/blob/master/src/log.js#L446
- https://github.com/orbitdb/ipfs-log/blob/master/src/log.js#L463
- https://github.com/orbitdb/ipfs-log/blob/master/src/log.js#L480
I would add it as the last argument (like you did in the constructor).
(And on that note, I feel we should generally pass the various "options" through an options object and not individual argument, but that's something for future, not for this PR)
I still think we should not add a setter but rather pass it in through function calls in order to avoid accidental usage/mutation (note that we don't use setter anywhere in the code).
What do you think?
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.
Sounds like the best solution, I'll update the PR today 👍 Thanks for pointing out the factory functions
@@ -128,15 +128,15 @@ apis.forEach((IPFS) => { | |||
if (i % 10 === 0) { | |||
log2 = new Log(ipfs, log2.id, log2.values, log2.heads) | |||
await log2.append('hi' + i) | |||
log2.join(log) | |||
await log2.join(log) |
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.
👍 to all these, they should've been async in the first place :) Thank you!
Was able to do a quick review now. Looking good! I think we should pass the verification function in the constructor is my biggest feedback, so let me know what you think! Thanks! ❤️ 😄 |
} catch (e) { | ||
console.error(e) | ||
} | ||
// log B (containing entries from items3) not joined due to it containing an invalid entry |
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.
👍
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.
Great that you added a test for this! ❤️
@haadcode PR updated with all the things! I think it's ready for merging now Unrelated things:
|
src/log.js
Outdated
* to the log itself and the verification function should return true | ||
* if the entry is valid and false if it is not. Logs containing entries | ||
* marked as invalid by this function will not be joined | ||
* |
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 great documentation! Thanks for adding it 👍
src/log.js
Outdated
* | ||
* @memberof Log | ||
*/ | ||
setCustomVerificationFunction (verifyEntry) { |
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.
What I meant with my previous comment about "no setter" was that we shouldn't have a function/setter at all that the user should/can call to set the verification function AFTER creating the Log instance, but that the only way to use a custom verifier is to pass it through the constructor (at creation time). Adding a new function to do that changes the API and doesn't fit the general idea of the design of the API as "operations on the log" as it changes the behaviour of the instance "dynamically". However, if we pass it in the constructor, it's explicit to the user and usage (ie. the only way to use "custom behaviour" is to pass it at instance creation time). Does that make sense?
If that makes sense, let's remove this function (but keep the documentation, it's awesome! perhaps move it to the constructor docs) as to not introduce it to the API of the log and we're good to merge 👍
Sorry for being picky about this one, I believe it's an important design decision even though it may be a seemingly small issue :) You've done fantastic job on the PR! 👍😃
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 problem @haadcode, I just misunderstood your comment about no setter 😄 I can see now that as you said, there are no other functions that make the Log a dynamically changeable structure so there is no place for this one either.
Added one more comment. Looking very good and close being able to merge. Regarding your other comments:
Tests on mater seem to run, so not sure why they're not running for you. I'll take a look and see what I can find.
Let's put that on the long list of "to-refactor at some point" :) 👍
Yup, agreed! Will hold off releasing 0.20.0 until this is finished and we can pull it in. |
I just ran the tests locally and they seem to run fine. I also noticed that we don't have CI on for forked PRs which I enabled now and I believe if you commit to this branch again, CI will run automatically and let you know if the tests run. If you're seeing some error for the tests locally, can you pass the errors/log and we'll take a look at what's going on? |
Oh, one more thing before merge: can you squash the commit into one and add the individual commit descriptions into that one commit? |
57185c5
to
f655d87
Compare
@haadcode squashed the commits, but circle failed the tests. Looks like it failed with the same identical problem I get on my machine If you can, try triggering a build on master by circle. It should fail the replication test with the same error, like on my machine |
@fazo96 thanks for squashing it! One more thing to change (see the comment re. the setter function) and we're ready to merge :) As for the tests, I re-triggered CI for this PR and it's now passing. Same for master. However, from the previous failed build, I can see how it fails:
Which sounds to me like a possible race condition in pubsub. Buffer1 and Buffer2 should both be 128, so there's one extra message sent... Really not sure how to catch this (and not something we need to figure out for this PR). @fazo96 does this fail on your computer on every run or just some times? |
f655d87
to
46a1848
Compare
Removed the setter and moved the docs into the constructor 👍 The replication test always failed for me, but the numbers change so it's probably some kind of nasty race condition |
* added docs and tests for custom verification * fix sync join calls in replication test * added verifyEntry constructor argument * add verifyEntry param to Factory functions. Don't use setter for it
Closing the PR as obsolete. The custom sorting function was implemented and can be passed in to a log through the constructor as the If you feel this PR was not addressed and solved, feel free to re-open it 👍 |
Closes #117
Content:
join
calls toawait
because before these changes, if the log was not signed there were no async operations in the join. However, the way I structured the code now there is always an async call toverifyEntries
that makesjoin
always happen asynchroniously. This broke many tests@haadcode I'm not good at naming stuff at all, so tell me if you want me to rename anything or change the way the custom verification function is passed.
I also saw some
TODOs
about moving verification stuff from theLog
to theEntry
. Maybe I can fit that in this PR