MatrixAI / js-db

Key-Value DB for TypeScript and JavaScript Applications
https://polykey.com
Apache License 2.0
5 stars 0 forks source link

Handle subleveldown opening errors via promise rejection #9

Closed CMCDragonkai closed 2 years ago

CMCDragonkai commented 2 years ago

Description

Derived from https://github.com/MatrixAI/js-encryptedfs/pull/58. When subleveldown is used, it ends up constructing the underlying database. This may cause an open error or other IO errors, such as when you try to re-use a sublevel after the root database has already been stopped then started again.

Tasks

  1. [x] Handle subleveldown errors
  2. [x] Add tests for when sublevels are re-use
  3. [x] Add types for all leveldb libraries
  4. [x] Integrate async-init

Final checklist

CMCDragonkai commented 2 years ago

Details of how this solution was discovered: https://github.com/MatrixAI/js-encryptedfs/pull/58#issuecomment-1010737577

And also upstream issue to make this easier in the future: https://github.com/Level/subleveldown/issues/109

CMCDragonkai commented 2 years ago

This is a good opportunity to integrate async-init anyway. So let's see if we can do this.

CMCDragonkai commented 2 years ago

This reproduced the bug with sublevels requiring recreation:

import DB from './src/DB';

async function main () {
  const db = await DB.createDB({
    dbPath: './tmp/db',
  });

  const mgrDomain = ['INodeManager'];
  const dataDomain = [mgrDomain[0], 'data'];
  let mgrDb = await db.level(mgrDomain[0]);
  let dataDb = await db.level(dataDomain[1], mgrDb);

  await db.put(['INodeManager', 'inodes', '123'], 'a', 'b');
  await db.stop();
  await db.start();

  // The levels
  mgrDb = await db.level(mgrDomain[0]);
  dataDb = await db.level(dataDomain[1], mgrDb);

  // this is where things are broken
  // it's probably because `dataDb` is not "recreated"
  await db.level('123', dataDb);
  console.log(await db.get(['INodeManager', 'inodes', '123'], 'a'));

  await db.stop();
}

main();