Skip to content

Commit e6f156f

Browse files
authored
fix watch when first one is destroyed (#44)
1 parent fd042e7 commit e6f156f

File tree

3 files changed

+52
-17
lines changed

3 files changed

+52
-17
lines changed

Diff for: index.js

+17
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const isOptions = require('is-options')
99
const hypercore = require('hypercore')
1010
const inherits = require('inherits')
1111
const alru = require('array-lru')
12+
const set = require('unordered-set')
1213

1314
const Extension = require('./lib/extension')
1415
const Node = require('./lib/node')
@@ -74,6 +75,22 @@ Object.defineProperty(HyperTrie.prototype, 'version', {
7475
}
7576
})
7677

78+
HyperTrie.prototype._removeWatch = function (w) {
79+
set.remove(this._watchers, w)
80+
}
81+
82+
HyperTrie.prototype._addWatch = function (w) {
83+
const self = this
84+
85+
set.add(this._watchers, w)
86+
if (this._watchers.length > 1 || !this.feed.sparse) return
87+
88+
this.feed.update({ ifAvailable: false }, function loop () {
89+
if (self._watchers.length === 0) return
90+
self.feed.update({ ifAvailable: false }, loop)
91+
})
92+
}
93+
7794
HyperTrie.prototype.reconnect = function (from, opts) {
7895
opts = opts ? Object.assign({}, opts, { reconnect: true }) : { reconnect: true }
7996
return this.diff(from, opts)

Diff for: lib/watch.js

+2-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
const set = require('unordered-set')
21
const inherits = require('inherits')
32
const events = require('events')
43

@@ -15,29 +14,15 @@ function Watch (db, prefix, onchange) {
1514
this._kicking = false
1615
this._index = 0
1716

18-
const self = this
19-
const feed = this._db.feed
20-
const watchers = this._db._watchers
21-
2217
if (onchange) this.on('change', onchange)
23-
set.add(watchers, this)
18+
this._db._addWatch(this)
2419
this.update()
25-
26-
if (watchers.length === 1 && feed.sparse) {
27-
feedUpdateLoop()
28-
}
29-
30-
function feedUpdateLoop () {
31-
if (self._destroyed) return
32-
// TODO: Expose a way to cancel this update when the watcher is destroyed, since it is not ifAvailable.
33-
feed.update({ ifAvailable: false }, feedUpdateLoop)
34-
}
3520
}
3621

3722
inherits(Watch, events.EventEmitter)
3823

3924
Watch.prototype.destroy = function () {
40-
set.remove(this._db._watchers, this)
25+
this._db._removeWatch(this)
4126
this._destroyed = true
4227
}
4328

Diff for: test/watch.js

+33
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,39 @@ tape('watch and stop watching', function (t) {
6161
db.put('foo/bar', 'baz')
6262
})
6363

64+
tape('watch, watch and stop watch first one', function (t) {
65+
t.plan(5 + 1)
66+
67+
const db = create()
68+
var bs = 5
69+
70+
db.ready(function () {
71+
const clone = create(db.key, { sparse: true })
72+
73+
const a = clone.watch('foo', function () {
74+
t.pass('got a update')
75+
a.destroy()
76+
})
77+
78+
const b = clone.watch('foo', function () {
79+
t.pass('got b update')
80+
81+
if (!--bs) {
82+
b.destroy()
83+
t.end()
84+
return
85+
}
86+
87+
db.put('foo/bar', 'baz')
88+
})
89+
90+
db.put('foo/bar', 'baz')
91+
92+
const stream = db.replicate(true, { live: true })
93+
stream.pipe(clone.replicate(false, { live: true })).pipe(stream)
94+
})
95+
})
96+
6497
tape('remote watch', function (t) {
6598
const db = create()
6699

0 commit comments

Comments
 (0)