Level / levelup

A wrapper for abstract-leveldown compliant stores, for Node.js and browsers.
MIT License
4.08k stars 266 forks source link

public levelup rc testing #472

Closed juliangruber closed 5 years ago

juliangruber commented 7 years ago

We should get as many people as possible to test levelup@2.0.0-rc1.

I'm thinking the following:

ralphtheninja commented 7 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)

ralphtheninja commented 7 years ago

@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.

ralphtheninja commented 7 years ago

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.

vweevers commented 7 years ago

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.

MeirionHughes commented 7 years ago

Surprised this problem didn't popup until now.

At least I contributed something useful in the end. 😁

vweevers commented 7 years ago

@ralphtheninja but why does it throw key cannot be null or undefined if the key is '[object Object]'?

ralphtheninja commented 7 years ago

@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
vweevers commented 7 years ago

Ah that makes sense 👍

ralphtheninja commented 7 years ago

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.

MeirionHughes commented 7 years ago

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.

ralphtheninja commented 7 years ago

@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.

MeirionHughes commented 7 years ago

@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.

ralphtheninja commented 7 years ago

@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.

vweevers commented 7 years ago

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)

npm (rc)