Closed juliangruber closed 5 years ago
If I do:
const leveldown = require('leveldown');
const encoding = require('encoding-down')
const levelup = require('levelup');
let db = levelup(
encoding(leveldown('./db'), {
keyEncoding: {
encode: function (a) { return a.name },
decode: function (b) { return { name: b } },
buffer: false,
type: "custom"
}
})
);
db.on('ready', () => {
async function main() {
await db.put({ name: "Hello" }, "World");
console.log(await db.get({ name: "Hello" }));
}
main().catch(console.log);
})
then it works, so there's some problems with deferred-leveldown (haven't found the exact problem yet)
@MeirionHughes I think I know why this happens. Before the database is opened, deferred-leveldown
defers the put operation, but it calls abstract-leveldown#put
which does this
key = this._serializeKey(key)
Which fucks up the key
if it's an object and works well if it's a buffer or a string.
So essentially { name: 'Hello' }
is converted to "[object Object]"
.
@juliangruber Any ideas on how to address this? Wasn't a problem before, since levelup
took care of the encode step, before deferred-leveldown
, so the deferred put-operation always had the correct encoding for key and value.
Just made this quick hack:
DeferredLevelDOWN.prototype._serializeKey = function (key) {
return key
}
and then it works fine. But not sure if this is the right approach and/or if it will mess up something else.
But not sure if this is the right approach
I think it is, because deferred-leveldown
is merely a layer (like encoding-down
, which also has identity functions for _serialize
) in between levelup and actual storage and so should not do any serialization.
Surprised this problem didn't popup until now.
Surprised this problem didn't popup until now.
At least I contributed something useful in the end. 😁
@ralphtheninja but why does it throw key cannot be null or undefined
if the key is '[object Object]'
?
@vweevers I think because when the deferred operation is actually run, then encoding-down
will apply the custom key-encoding and do
> '[object Object]'.name
undefined
Ah that makes sense 👍
At least I contributed something useful. :grin:
Awesome that you found this.
I think it is, because deferred-leveldown is merely a layer (like encoding-down, which also has identity functions for _serialize) in between levelup and actual storage and so should not do any serialization.
Aye. So maybe it should be ok to add ._serializeKey()
and ._serializeValue()
that are no-ops.
Surprised this problem didn't popup until now.
We clearly haven't tested it enough. We should write some tests for it. Both in deferred-leveldown
and in levelup
.
I've also noticed one of the tests isn't failing on old usage:
https://github.com/Level/levelup/blob/master/test/create-stream-vs-put-racecondition.js#L74 https://github.com/Level/levelup/blob/master/test/create-stream-vs-put-racecondition.js#L83
this was picked up by typescript via vscode.
@MeirionHughes Nice catch. We could do some sanity check on the db
parameter in the levelup constructor, e.g. assert that it's not a string, which would make these tests fail and then we rewrite the tests.
@ralphtheninja that test doesn't fail because it doesn't run: file is create-stream-vs-put-racecondition.js
and the runner looks for *-test.js
.
It was the same before the changes to allow the typescript to run each test: https://github.com/Level/levelup/blob/e152d83ce646a67e91baa7a302ccd6bb3bb154e4/buster.js#L5
I was going to do a quick pr, but the test does still fail when given a leveldown instance.
@MeirionHughes Would you mind making a separate issue for this? These threads have a tendency to get really long and contain multiple discussions. I have been traveling and haven't had the time to deal with the latest updates, but I will catch up on it this week.
Also, I never bothered to release 2.0.0, maybe we can get it out this week instead.
Doesn't matter anymore now, or at all, but just a cool thing. We could have had an rc badge. 😿
![npm (rc)](https://img.shields.io/npm/v/levelup/rc.svg)
We should get as many people as possible to test
levelup@2.0.0-rc1
.I'm thinking the following:
level-sublevelsubleveldown