Skip to content
This repository was archived by the owner on Dec 2, 2024. It is now read-only.

Commit fc3f3d5

Browse files
committed
Fix for await...of db.iterator()
1 parent ff1ba48 commit fc3f3d5

File tree

3 files changed

+66
-18
lines changed

3 files changed

+66
-18
lines changed

leveldown.js

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const duplexify = require('duplexify')
4-
const { AbstractLevelDOWN } = require('abstract-leveldown')
4+
const { AbstractLevelDOWN, AbstractIterator } = require('abstract-leveldown')
55
const eos = require('end-of-stream')
66
const ids = require('numeric-id-map')
77
const lpstream = require('length-prefixed-stream')
@@ -287,7 +287,7 @@ Multilevel.prototype._close = function (cb) {
287287
this._streaming.once('close', () => cb())
288288
this._streaming.destroy()
289289
} else {
290-
process.nextTick(cb)
290+
this._nextTick(cb)
291291
}
292292
}
293293

@@ -298,9 +298,9 @@ Multilevel.prototype._iterator = function (opts) {
298298

299299
function noop () {}
300300

301-
// TODO: extend AbstractIterator, passing db to ctor
302-
function Iterator (parent, opts) {
303-
this._parent = parent
301+
function Iterator (db, opts) {
302+
AbstractIterator.call(this, db)
303+
304304
this._keyAsBuffer = opts.keyAsBuffer
305305
this._valueAsBuffer = opts.valueAsBuffer
306306
this._options = opts
@@ -315,47 +315,73 @@ function Iterator (parent, opts) {
315315
callback: null
316316
}
317317

318-
req.id = parent._iterators.add(req)
318+
req.id = this.db._iterators.add(req)
319319

320320
this._read = 0
321321
this._ack = Math.floor(req.batch / 2)
322322
this._req = req
323-
this._parent._write(req)
323+
this.db._write(req)
324324
}
325325

326-
Iterator.prototype.next = function (cb) {
326+
Object.setPrototypeOf(Iterator.prototype, AbstractIterator.prototype)
327+
328+
// TODO: implement _next() instead
329+
Iterator.prototype.next = function (callback) {
330+
// In callback mode, we return `this`
331+
let ret = this
332+
333+
if (callback === undefined) {
334+
ret = new Promise(function (resolve, reject) {
335+
callback = function (err, key, value) {
336+
if (err) reject(err)
337+
else if (key === undefined && value === undefined) resolve()
338+
else resolve([key, value])
339+
}
340+
})
341+
}
342+
327343
this._req.callback = null
328344

329345
if (this._req.pending.length) {
330346
this._read++
331347
if (this._read >= this._ack) {
332348
this._read = 0
333349
this._req.options = null
334-
this._parent._write(this._req)
350+
this.db._write(this._req)
335351
}
336352

337353
const next = this._req.pending.shift()
338-
if (next.error) return cb(decodeError(next.error))
339354

340-
if (!next.key && !next.value) return cb()
355+
if (next.error) {
356+
callback(decodeError(next.error))
357+
return ret
358+
}
359+
360+
if (!next.key && !next.value) {
361+
callback()
362+
return ret
363+
}
341364

342365
this._options.gt = next.key
343366
if (this._options.limit > 0) this._options.limit--
344367

345368
const key = decodeValue(next.key, this._keyAsBuffer)
346369
const val = decodeValue(next.value, this._valueAsBuffer)
347-
return cb(undefined, key, val)
370+
371+
callback(undefined, key, val)
372+
return ret
348373
}
349374

350-
this._req.callback = cb
375+
this._req.callback = callback
376+
return ret
351377
}
352378

353-
Iterator.prototype.end = function (cb) {
379+
Iterator.prototype._end = function (cb) {
354380
this._req.batch = 0
355-
this._parent._write(this._req)
356-
this._parent._iterators.remove(this._req.id)
357-
this._parent._flushMaybe()
358-
if (cb) process.nextTick(cb)
381+
this.db._write(this._req)
382+
this.db._iterators.remove(this._req.id)
383+
this.db._flushMaybe()
384+
this._nextTick(cb)
359385
}
360386

361387
function decodeError (err) {

server.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ Iterator.prototype.next = function () {
203203
}
204204

205205
Iterator.prototype.end = function () {
206+
if (this._ended) return
206207
this._ended = true
207208
this._iterator.end(noop)
208209
}

test/basic.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,24 @@ tape('read stream (gt)', function (t) {
237237
}))
238238
})
239239
})
240+
241+
tape('for await...of iterator', function (t) {
242+
const db = factory()
243+
const stream = multileveldown.server(db)
244+
const client = multileveldown.client()
245+
246+
stream.pipe(client.createRpcStream()).pipe(stream)
247+
248+
client.batch([{ type: 'put', key: 'hello', value: 'world' }, { type: 'put', key: 'hej', value: 'verden' }], async function (err) {
249+
t.error(err, 'no err')
250+
251+
const entries = []
252+
253+
for await (const [key, value] of client.iterator()) {
254+
entries.push([key, value])
255+
}
256+
257+
t.same(entries, [['hej', 'verden'], ['hello', 'world']])
258+
t.end()
259+
})
260+
})

0 commit comments

Comments
 (0)