Skip to content

Commit

Permalink
Implement explicit snapshots
Browse files Browse the repository at this point in the history
See Level/community#118. Depends on
Level/abstract-level#93.

Category: addition
  • Loading branch information
vweevers committed Dec 23, 2024
1 parent f394ea3 commit 22e9e64
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ for await (const [key, value] of db.iterator({ gt: 'a' })) {

## API

The API of `memory-level` follows that of [`abstract-level`](https://github.com/Level/abstract-level) with a one additional constructor option (see below). The `createIfMissing` and `errorIfExists` options of `abstract-level` are not relevant here. Data is discarded when the last reference to the database is released (i.e. `db = null`). Closing or reopening the database has no effect on the data. Data is _not_ copied: when storing a Buffer value for example, subsequent mutations to that Buffer will affect the stored data too.
The API of `memory-level` follows that of [`abstract-level`](https://github.com/Level/abstract-level) with one additional constructor option (see below). The `createIfMissing` and `errorIfExists` options of `abstract-level` are not relevant here. Both implicit and explicit snapshots are supported. Data is discarded when the last reference to the database is released (i.e. `db = null`). Closing or reopening the database has no effect on the data. Data is _not_ copied: when storing a Buffer value for example, subsequent mutations to that Buffer will affect the stored data too.

### `db = new MemoryLevel([options])`

Expand Down
45 changes: 37 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ const {
AbstractLevel,
AbstractIterator,
AbstractKeyIterator,
AbstractValueIterator
AbstractValueIterator,
AbstractSnapshot
} = require('abstract-level')

const ModuleError = require('module-error')
Expand Down Expand Up @@ -59,7 +60,7 @@ function lte (value) {
class MemoryIterator extends AbstractIterator {
constructor (db, options) {
super(db, options)
this[kInit](db[kTree], options)
this[kInit](db, options)
}

async _next () {
Expand Down Expand Up @@ -103,7 +104,7 @@ class MemoryIterator extends AbstractIterator {
class MemoryKeyIterator extends AbstractKeyIterator {
constructor (db, options) {
super(db, options)
this[kInit](db[kTree], options)
this[kInit](db, options)
}

async _next () {
Expand Down Expand Up @@ -145,7 +146,7 @@ class MemoryKeyIterator extends AbstractKeyIterator {
class MemoryValueIterator extends AbstractValueIterator {
constructor (db, options) {
super(db, options)
this[kInit](db[kTree], options)
this[kInit](db, options)
}

async _next (options) {
Expand Down Expand Up @@ -187,7 +188,11 @@ class MemoryValueIterator extends AbstractValueIterator {
}

for (const Ctor of [MemoryIterator, MemoryKeyIterator, MemoryValueIterator]) {
Ctor.prototype[kInit] = function (tree, options) {
Ctor.prototype[kInit] = function (db, options) {
const tree = options.snapshot != null
? options.snapshot[kTree]
: db[kTree]

this[kReverse] = options.reverse
this[kOptions] = options

Expand Down Expand Up @@ -281,6 +286,7 @@ class MemoryLevel extends AbstractLevel {

super({
seek: true,
explicitSnapshots: true,
permanence: false,
createIfMissing: false,
errorIfExists: false,
Expand All @@ -305,12 +311,20 @@ class MemoryLevel extends AbstractLevel {
}

async _get (key, options) {
const tree = options.snapshot != null
? options.snapshot[kTree]
: this[kTree]

// Is undefined if not found
return this[kTree].get(key)
return tree.get(key)
}

async _getMany (keys, options) {
return keys.map(key => this[kTree].get(key))
const tree = options.snapshot != null
? options.snapshot[kTree]
: this[kTree]

return keys.map(getFromThis, tree)
}

async _del (key, options) {
Expand All @@ -335,7 +349,7 @@ class MemoryLevel extends AbstractLevel {
}

async _clear (options) {
if (options.limit === -1 && !Object.keys(options).some(isRangeOption)) {
if (options.limit === -1 && !Object.keys(options).some(isRangeOption) && !options.snapshot) {
// Delete everything by creating a new empty tree.
this[kTree] = createRBT(compare)
return
Expand Down Expand Up @@ -374,6 +388,17 @@ class MemoryLevel extends AbstractLevel {
_values (options) {
return new MemoryValueIterator(this, options)
}

_snapshot (options) {
return new MemorySnapshot(this[kTree], options)
}
}

class MemorySnapshot extends AbstractSnapshot {
constructor (tree, options) {
super(options)
this[kTree] = tree
}
}

exports.MemoryLevel = MemoryLevel
Expand All @@ -391,6 +416,10 @@ if (typeof process !== 'undefined' && !process.browser && typeof global !== 'und
breathe = async function () {}
}

function getFromThis (key) {
return this.get(key)
}

function isRangeOption (k) {
return rangeOptions.has(k)
}

0 comments on commit 22e9e64

Please sign in to comment.