Comparing version 2.9.2 to 2.10.0
104
index.js
@@ -7,2 +7,3 @@ const codecs = require('codecs') | ||
const ReadyResource = require('ready-resource') | ||
const debounce = require('debounceify') | ||
@@ -297,3 +298,6 @@ const RangeIterator = require('./iterators/range') | ||
this._onappendBound = this._view ? null : this._onappend.bind(this) | ||
this._ontruncateBound = this._view ? null : this._ontruncate.bind(this) | ||
this._watchers = this._onappendBound ? [] : null | ||
this._entryWatchers = this._onappendBound ? [] : null | ||
this._batches = [] | ||
@@ -303,3 +307,3 @@ | ||
this.core.on('append', this._onappendBound) | ||
if (this.core.isAutobase) this.core.on('truncate', this._onappendBound) | ||
this.core.on('truncate', this._ontruncateBound) | ||
} | ||
@@ -404,2 +408,16 @@ | ||
async getAndWatch (key) { | ||
if (!this._watchers) throw new Error('Can only watch the main bee instance') | ||
const watcher = new EntryWatcher(this, key) | ||
await watcher._debouncedUpdate() | ||
if (this.closing) { | ||
await watcher.close() | ||
throw new Error('Bee closed') | ||
} | ||
return watcher | ||
} | ||
_onappend () { | ||
@@ -409,4 +427,18 @@ for (const watcher of this._watchers) { | ||
} | ||
for (const watcher of this._entryWatchers) { | ||
watcher._onappend() | ||
} | ||
} | ||
_ontruncate () { | ||
for (const watcher of this._watchers) { | ||
watcher._ontruncate() | ||
} | ||
for (const watcher of this._entryWatchers) { | ||
watcher._ontruncate() | ||
} | ||
} | ||
_makeSnapshot () { | ||
@@ -469,3 +501,3 @@ // TODO: better if we could encapsulate this in hypercore in the future | ||
this.core.off('append', this._onappendBound) | ||
if (this.core.isAutobase) this.core.off('truncate', this._onappendBound) | ||
this.core.off('truncate', this._ontruncateBound) | ||
@@ -477,2 +509,8 @@ while (this._watchers.length) { | ||
if (this._entryWatchers) { | ||
while (this._entryWatchers.length) { | ||
await this._entryWatchers[this._entryWatchers.length - 1].close() | ||
} | ||
} | ||
while (this._batches.length) { | ||
@@ -900,2 +938,60 @@ await this._batches[this._batches.length - 1].close() | ||
class EntryWatcher extends ReadyResource { | ||
constructor (bee, key) { | ||
super() | ||
this.index = bee._entryWatchers.push(this) - 1 | ||
this.bee = bee | ||
this.key = key | ||
this.node = null | ||
this._forceUpdate = false | ||
this._debouncedUpdate = debounce(this._processUpdate.bind(this)) | ||
} | ||
_close () { | ||
const top = this.bee._entryWatchers.pop() | ||
if (top !== this) { | ||
top.index = this.index | ||
this.bee._entryWatchers[top.index] = top | ||
} | ||
} | ||
_onappend () { | ||
this._debouncedUpdate() | ||
} | ||
_ontruncate () { | ||
this._forceUpdate = true | ||
this._debouncedUpdate() | ||
} | ||
async _processUpdate () { | ||
const force = this._forceUpdate | ||
this._forceUpdate = false | ||
let newNode | ||
try { | ||
newNode = await this.bee.get(this.key) | ||
} catch (e) { | ||
if (e.code === 'SNAPSHOT_NOT_AVAILABLE') { | ||
// There was a truncate event before the get resolved | ||
// So this handler will run again anyway | ||
return | ||
} else if (this.bee.closing) { | ||
this.close().catch(safetyCatch) | ||
return | ||
} | ||
this.emit('error', e) | ||
return | ||
} | ||
if (force || newNode?.seq !== this.node?.seq) { | ||
this.node = newNode | ||
this.emit('update') | ||
} | ||
} | ||
} | ||
class Watcher extends ReadyResource { | ||
@@ -934,2 +1030,6 @@ constructor (bee, range, opts = {}) { | ||
_ontruncate () { | ||
if (this.core.isAutobase) this._onappend() | ||
} | ||
_onappend () { | ||
@@ -936,0 +1036,0 @@ // TODO: this is a light hack / fix for non-sparse session reporting .length's inside batches |
{ | ||
"name": "hyperbee", | ||
"version": "2.9.2", | ||
"version": "2.10.0", | ||
"description": "An append-only B-tree running on a Hypercore.", | ||
@@ -14,2 +14,3 @@ "main": "index.js", | ||
"codecs": "^3.0.0", | ||
"debounceify": "^1.0.0", | ||
"mutexify": "^1.4.0", | ||
@@ -16,0 +17,0 @@ "protocol-buffers-encodings": "^1.2.0", |
@@ -262,2 +262,12 @@ # Hyperbee 🐝 | ||
#### `const entryWatcher = await db.getAndWatch(key)` | ||
Returns a watcher which listens to changes on the given key. | ||
`entryWatcher.node` contains the current entry in the same format as the result of `bee.get(key)`, and will be updated as it changes. | ||
You can listen to `entryWatcher.on('update')` to be notified when the value of node has changed. | ||
Call `await watcher.close()` to stop the watcher. | ||
#### `const watcher = db.watch([range])` | ||
@@ -264,0 +274,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
87200
2436
348
8
+ Addeddebounceify@^1.0.0
+ Addeddebounceify@1.1.0(transitive)