You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -381,6 +383,7 @@ The `gte` and `lte` range options take precedence over `gt` and `lt` respectivel
381
383
-`values` (boolean, default: `true`): whether to return the value of each entry. If set to `false`, the iterator will yield values that are `undefined`. Prefer to use `db.values()` instead.
382
384
-`keyEncoding`: custom key encoding for this iterator, used to encode range options, to encode `seek()` targets and to decode keys.
383
385
-`valueEncoding`: custom value encoding for this iterator, used to decode values.
386
+
-`signal`: an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to [abort read operations on the iterator](#aborting-iterators).
384
387
385
388
Lastly, an implementation is free to add its own options.
Call the function `fn` at a later time when [`db.status`](#dbstatus) changes to `'open'` or `'closed'`. Used by `abstract-level` itself to implement "deferred open" which is a feature that makes it possible to call methods like `db.put()` before the database has finished opening. The `defer()` method is exposed for implementations and plugins to achieve the same on their custom methods:
537
+
Call the function `fn` at a later time when [`db.status`](#dbstatus) changes to `'open'` or `'closed'`. Known as a _deferred operation_. Used by `abstract-level` itself to implement "deferred open" which is a feature that makes it possible to call methods like `db.put()` before the database has finished opening. The `defer()` method is exposed for implementations and plugins to achieve the same on their custom methods:
535
538
536
539
```js
537
540
db.foo=function (key) {
@@ -543,9 +546,13 @@ db.foo = function (key) {
543
546
}
544
547
```
545
548
549
+
The optional `options` object may contain:
550
+
551
+
-`signal`: an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to abort the deferred operation. When aborted (now or later) the `fn` function will not be called.
552
+
546
553
When deferring a custom operation, do it early: after normalizing optional arguments but before encoding (to avoid double encoding and to emit original input if the operation has events) and before any _fast paths_ (to avoid calling back before the database has finished opening). For example, `db.batch([])` has an internal fast path where it skips work if the array of operations is empty. Resources that can be closed on their own (like iterators) should however first check such state before deferring, in order to reject operations after close (including when the database was reopened).
547
554
548
-
### `db.deferAsync(fn)`
555
+
### `db.deferAsync(fn[, options])`
549
556
550
557
Similar to `db.defer(fn)` but for asynchronous work. Returns a promise, which waits for [`db.status`](#dbstatus) to change to `'open'` or `'closed'` and then calls `fn` which itself must return a promise. This allows for recursion:
551
558
@@ -559,6 +566,10 @@ db.foo = async function (key) {
559
566
}
560
567
```
561
568
569
+
The optional `options` object may contain:
570
+
571
+
-`signal`: an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to abort the deferred operation. When aborted (now or later) the `fn` function will not be called, and the promise returned by `deferAsync()` will be rejected with a [`LEVEL_ABORTED`](#errors) error.
Iterators take an experimental `signal` option that, once signaled, aborts an in-progress read operation (if any) and rejects subsequent reads. The relevant promise will be rejected with a [`LEVEL_ABORTED`](#errors) error. Aborting does not close the iterator, because closing is asynchronous and may result in an error that needs a place to go. This means signals should be used together with a pattern that automatically closes the iterator:
738
+
739
+
```js
740
+
constabortController=newAbortController()
741
+
constsignal=abortController.signal
742
+
743
+
// Will result in 'aborted' log
744
+
abortController.abort()
745
+
746
+
try {
747
+
forawait (constentryofdb.iterator({ signal })) {
748
+
console.log(entry)
749
+
}
750
+
} catch (err) {
751
+
if (err.code==='LEVEL_ABORTED') {
752
+
console.log('aborted')
753
+
}
754
+
}
755
+
```
756
+
757
+
Otherwise, close the iterator explicitly:
758
+
759
+
```js
760
+
constiterator=db.iterator({ signal })
761
+
762
+
try {
763
+
constentries=awaititerator.nextv(10)
764
+
} catch (err) {
765
+
if (err.code==='LEVEL_ABORTED') {
766
+
console.log('aborted')
767
+
}
768
+
} finally {
769
+
awaititerator.close()
770
+
}
771
+
```
772
+
724
773
### `keyIterator`
725
774
726
775
A key iterator has the same interface as `iterator` except that its methods yield keys instead of entries. Usage is otherwise the same.
@@ -1161,6 +1210,10 @@ When `iterator.next()` or `seek()` was called while a previous `next()` call was
1161
1210
1162
1211
When an operation was made on a chained batch while it was closing or closed, which may also be the result of the database being closed or that `write()` was called on the chained batch.
1163
1212
1213
+
#### `LEVEL_ABORTED`
1214
+
1215
+
When an operation was aborted by the user.
1216
+
1164
1217
#### `LEVEL_ENCODING_NOT_FOUND`
1165
1218
1166
1219
When a `keyEncoding` or `valueEncoding` option specified a named encoding that does not exist.
@@ -1564,6 +1617,14 @@ class ExampleSublevel extends AbstractSublevel {
1564
1617
1565
1618
The first argument to this constructor must be an instance of the relevant `AbstractLevel` implementation. The constructor will set `iterator.db` which is used (among other things) to access encodings and ensures that `db` will not be garbage collected in case there are no other references to it. The `options` argument must be the original `options` object that was passed to `db._iterator()` and it is therefore not (publicly) possible to create an iterator via constructors alone.
1566
1619
1620
+
The `signal` option, if any and once signaled, should abort an in-progress `_next()`, `_nextv()` or `_all()` call and reject the promise returned by that call with a [`LEVEL_ABORTED`](#errors) error. Doing so is optional until a future semver-major release. Responsibilities are divided as follows:
1621
+
1622
+
1. Before a database has finished opening, `abstract-level` handles the signal
1623
+
2. While a call is in progress, the implementation handles the signal
1624
+
3. Once the signal is aborted, `abstract-level` rejects further calls.
1625
+
1626
+
A method like `_next()` therefore doesn't have to check the signal _before_ it start its asynchronous work, only _during_ that work. Whether to respect the signal and on which (potentially long-running) methods, is up to the implementation.
1627
+
1567
1628
#### `iterator._next()`
1568
1629
1569
1630
Advance to the next entry and yield that entry. Must return a promise. If an error occurs, reject the promise. If the natural end of the iterator has been reached, resolve the promise with `undefined`. Otherwise resolve the promise with an array containing a `key` and `value`. If a `limit` was set and the iterator already yielded that many entries (via any of the methods) then `_next()` will not be called.
Copy file name to clipboardExpand all lines: UPGRADING.md
+2-4Lines changed: 2 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -202,7 +202,7 @@ As for why that last example works yet the same is not supported on a chained ba
202
202
203
203
#### 2.1. Promises all the way
204
204
205
-
All private methods that previously took a callback now use a promise. For example, the function signature `_get(key, options, callback)` has changed to `async _get(key, options)`. Same as in the public API, the new function signatures are predictable and the only method that requires special attention is `iterator._next()`. Which in addition now also takes an `options` argument. For details, please see the updated [README](./README.md#private-api-for-implementors).
205
+
All private methods that previously took a callback now use a promise. For example, the function signature `_get(key, options, callback)` has changed to `async _get(key, options)`. Same as in the public API, the new function signatures are predictable and the only method that requires special attention is `iterator._next()`. For details, please see the updated [README](./README.md#private-api-for-implementors).
206
206
207
207
#### 2.2. Ticks
208
208
@@ -240,9 +240,7 @@ class ExampleLevel extends AbstractLevel {
240
240
241
241
#### 2.3. A new way to abort iterator work
242
242
243
-
_This section is incomplete._
244
-
245
-
Closing an iterator now aborts work, if supported by implementation. The undocumented `abortOnClose` option of iterators (added as a workaround for `many-level`) has been removed in favor of AbortSignal.
243
+
Iterators now take an experimental `signal` option that is an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal). You can use the `signal` to abort an in-progress `_next()`, `_nextv()` or `_all()` call. Doing so is optional until a future semver-major release.
0 commit comments