Skip to content

Commit

Permalink
Bump deferred-leveldown from 6.x to 7.x
Browse files Browse the repository at this point in the history
As well as the encoding-down and memdown devDependencies.

Adds `db.status` and `db.isOperational()` for API parity.

Ref Level/deferred-leveldown#90
  • Loading branch information
vweevers committed Sep 30, 2021
1 parent b66088a commit 47e5c57
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 28 deletions.
32 changes: 27 additions & 5 deletions lib/levelup.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function LevelUP (db, options, callback) {

this.options = getOptions(options)
this._db = db
this.db = new DeferredLevelDOWN(db)
this.db = null
this.open(callback || ((err) => {
if (err) this.emit('error', err)
}))
Expand Down Expand Up @@ -88,6 +88,19 @@ LevelUP.prototype.emit = EventEmitter.prototype.emit
LevelUP.prototype.once = EventEmitter.prototype.once
inherits(LevelUP, EventEmitter)

// TODO: docs and tests
Object.defineProperty(LevelUP.prototype, 'status', {
enumerable: true,
get () {
return this.db.status
}
})

// TODO: docs and tests
LevelUP.prototype.isOperational = function () {
return this.db.status === 'open' || this.db.status === 'opening'
}

LevelUP.prototype.open = function (opts, callback) {
if (typeof opts === 'function') {
callback = opts
Expand All @@ -100,16 +113,21 @@ LevelUP.prototype.open = function (opts, callback) {
opts = this.options
}

if (this.isOpen()) {
// 1) Don't check db.status until levelup has opened,
// in order for levelup events to be consistent
if (this.db && this.isOpen()) {
nextTick(callback, null, this)
return callback.promise
}

if (this._isOpening()) {
if (this.db && this._isOpening()) {
this.once('open', () => { callback(null, this) })
return callback.promise
}

// 2) Instead let deferred-leveldown handle already-open cases.
// TODO: ideally though, levelup would have its own status
this.db = new DeferredLevelDOWN(this._db)
this.emit('opening')

this.db.open(opts, (err) => {
Expand All @@ -134,7 +152,6 @@ LevelUP.prototype.close = function (callback) {
callback(err, ...rest)
})
this.emit('closing')
this.db = new DeferredLevelDOWN(this._db)
} else if (this.isClosed()) {
nextTick(callback)
} else if (this.db.status === 'closing') {
Expand All @@ -148,14 +165,17 @@ LevelUP.prototype.close = function (callback) {
return callback.promise
}

// TODO: remove in future major
LevelUP.prototype.isOpen = function () {
return this.db.status === 'open'
}

// TODO: remove in future major
LevelUP.prototype._isOpening = function () {
return this.db.status === 'opening'
}

// TODO: remove in future major
LevelUP.prototype.isClosed = function () {
return (/^clos|new/).test(this.db.status)
}
Expand Down Expand Up @@ -306,10 +326,12 @@ LevelUP.prototype.toString = function () {
LevelUP.prototype.type = 'levelup'

function maybeError (db, callback) {
if (!db._isOpening() && !db.isOpen()) {
if (!db.isOperational()) {
nextTick(callback, new ReadError('Database is not open'))
return true
}

return false
}

LevelUP.errors = errors
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
],
"dependencies": {
"catering": "^2.0.0",
"deferred-leveldown": "^6.0.0",
"deferred-leveldown": "^7.0.0",
"level-errors": "^3.0.0",
"level-iterator-stream": "^5.0.0",
"level-supports": "^2.0.0",
"level-supports": "^2.0.1",
"queue-microtask": "^1.2.3"
},
"devDependencies": {
Expand All @@ -41,12 +41,12 @@
"concat-stream": "^2.0.0",
"delayed": "^2.0.0",
"dependency-check": "^4.1.0",
"encoding-down": "^7.0.0",
"encoding-down": "^7.1.0",
"faucet": "^0.0.1",
"hallmark": "^3.1.0",
"level-community": "^3.0.0",
"level-concat-iterator": "^3.0.0",
"memdown": "^6.0.0",
"memdown": "^6.1.0",
"nyc": "^15.1.0",
"run-parallel": "^1.2.0",
"run-series": "^1.1.8",
Expand Down
32 changes: 20 additions & 12 deletions test/deferred-open-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ module.exports = function (test, testCommon) {
test('deferred open(): put() and get() on new database', function (t) {
// 1) open database without callback, opens in next tick
const db = testCommon.factory()
t.ok(typeof db === 'object' && db !== null)

parallel([
// 2) insert 3 values with put(), these should be deferred until the database is actually open
Expand All @@ -34,15 +33,29 @@ module.exports = function (test, testCommon) {
})
})

// we should still be in a state of limbo down here, not opened or closed, but 'new'
t.is(db.isOpen(), false)
t.is(db.isClosed(), false)
t.is(db.status, 'opening')
})

test('deferred open(): put() and get() on reopened database', async function (t) {
const db = testCommon.factory()

await db.close()
t.is(db.status, 'closed')

db.open(() => {})
t.is(db.status, 'opening')

await db.put('beep', 'boop')

t.is(db.status, 'open')
t.is(await db.get('beep', { asBuffer: false }), 'boop')

await db.close()
})

test('deferred open(): batch() on new database', function (t) {
// 1) open database without callback, opens in next tick
const db = testCommon.factory()
t.ok(typeof db === 'object' && db !== null)

// 2) insert 3 values with batch(), these should be deferred until the database is actually open
db.batch([
Expand All @@ -66,15 +79,12 @@ module.exports = function (test, testCommon) {
})
})

// we should still be in a state of limbo down here, not opened or closed, but 'new'
t.is(db.isOpen(), false)
t.is(db.isClosed(), false)
t.is(db.status, 'opening')
})

test('deferred open(): chained batch() on new database', function (t) {
// 1) open database without callback, opens in next tick
const db = testCommon.factory()
t.ok(typeof db === 'object' && db !== null)

// 2) insert 3 values with batch(), these should be deferred until the database is actually open
db.batch()
Expand All @@ -98,9 +108,7 @@ module.exports = function (test, testCommon) {
})
})

// we should still be in a state of limbo down here, not opened or closed, but 'new'
t.is(db.isOpen(), false)
t.is(db.isClosed(), false)
t.is(db.status, 'opening')
})

testCommon.streams && test('deferred open(): test deferred ReadStream', function (t) {
Expand Down
17 changes: 16 additions & 1 deletion test/maybe-error-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = function (test, testCommon) {
t.is(err.message, 'Database is not open')
})
t.is(sync, false, '.put cb called asynchronously')
done()
done() // TODO: called too soon, we still have 2 pending assertions
})
})
})
Expand Down Expand Up @@ -72,4 +72,19 @@ module.exports = function (test, testCommon) {
})
})
})

test('maybeError() should be called async: getMany()', function (t) {
discardable(t, testCommon, function (db, done) {
db.close(function () {
t.is(db.status, 'closed', 'db is closed')
let sync = false
db.getMany(['key'], function (err) {
sync = true
t.is(err && err.message, 'Database is not open')
done()
})
t.is(sync, false, '.getMany cb called asynchronously')
})
})
})
}
5 changes: 3 additions & 2 deletions test/open-patchsafe-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,16 @@ module.exports = function (test, testCommon) {

function makeTest (fn) {
return function (t) {
// 1) open database without callback, opens in next tick
// Open database without callback, opens in next tick
const db = testCommon.factory()

fn(t, db, function (err) {
t.ifError(err, 'no test error')
db.close(t.end.bind(t))
})

// we should still be in a state of limbo down here, not opened or closed, but 'new'
// Expected state is 'opening'
t.is(db._isOpening(), true)
t.is(db.isOpen(), false)
t.is(db.isClosed(), false)
}
Expand Down
9 changes: 5 additions & 4 deletions test/self/manifest-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ test('manifest: additionalMethod is proxied', function (t) {
mem.supports = { additionalMethods: { beep: true } }

const db = levelup(mem)
const noop = () => {}

t.is(typeof db.beep, 'function')
t.is(typeof levelup.prototype.beep, 'undefined')

db.beep()
db.beep(noop)
t.is(mem.beep.callCount, 0, 'deferred')

db.on('open', function () {
t.is(mem.beep.callCount, 1)
t.same(mem.beep.getCall(0).args, [])
t.same(mem.beep.getCall(0).args, [noop])

db.beep('boop')
t.same(mem.beep.getCall(1).args, ['boop'])
db.beep('boop', noop)
t.same(mem.beep.getCall(1).args, ['boop', noop])

db.close(t.end.bind(t))
})
Expand Down

0 comments on commit 47e5c57

Please sign in to comment.