Skip to content

Commit 8bfbb20

Browse files
feat: add unwantBlocks method
1 parent 6ad08e7 commit 8bfbb20

File tree

5 files changed

+254
-153
lines changed

5 files changed

+254
-153
lines changed

API.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ Fetch a single block.
2727

2828
Fetch multiple blocks.
2929

30+
### `unwantBlocks(keys)`
31+
32+
- `keys: []Multihash`
33+
34+
Cancel previously requested keys, forcefully. That means they are removed from the
35+
wantlist independent of how many other resources requested these keys. Callbacks
36+
attached to `getBlock` are errored with `Error('manual unwant: key')`.
37+
3038
### `cancelWants(keys)`
3139

3240
- `keys: []Multihash`

src/index.js

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ module.exports = class Bitwap {
138138
cb(err, block)
139139
}
140140

141-
this.getBlocks([key], (err, res) => {
142-
if (err) {
143-
return done(err)
141+
this.getBlocks([key], (errs, res) => {
142+
if (errs) {
143+
return done(errs[0])
144144
}
145145

146146
done(null, res[0])
@@ -154,14 +154,53 @@ module.exports = class Bitwap {
154154

155155
getBlocks (keys, cb) {
156156
const blocks = []
157-
const finish = (block) => {
158-
blocks.push(block)
159-
log('finish: %s/%s', blocks.length, keys.length)
160-
if (blocks.length === keys.length) {
157+
const errs = []
158+
const unwantListeners = {}
159+
const blockListeners = {}
160+
const unwantEvent = (key) => `unwant:${key.toString('hex')}`
161+
const blockEvent = (key) => `block:${key.toString('hex')}`
162+
163+
const cleanupListeners = () => {
164+
keys.forEach((key) => {
165+
this.notifications.removeListener(unwantEvent(key), unwantListeners[key])
166+
this.notifications.removeListener(blockEvent(key), blockListeners[key])
167+
})
168+
}
169+
170+
const addListeners = () => {
171+
keys.forEach((key) => {
172+
unwantListeners[key] = () => {
173+
finish(new Error(`manual unwant: ${key.toString('hex')}`))
174+
}
175+
176+
blockListeners[key] = (block) => {
177+
finish(null, block)
178+
}
179+
180+
this.notifications.once(unwantEvent(key), unwantListeners[key])
181+
this.notifications.once(blockEvent(key), blockListeners[key])
182+
})
183+
}
184+
185+
const finish = (err, block) => {
186+
if (err) {
187+
errs.push(err)
188+
}
189+
if (block) {
190+
blocks.push(block)
191+
}
192+
193+
if (blocks.length + errs.length === keys.length) {
194+
cleanupListeners()
195+
if (errs.length > 0) {
196+
return cb(errs, blocks)
197+
}
161198
cb(null, blocks)
162199
}
163200
}
164201

202+
addListeners()
203+
165204
keys.forEach((key) => {
166205
// Sanity check, we don't want to announce looking for blocks
167206
// when we might have them ourselves
@@ -175,7 +214,7 @@ module.exports = class Bitwap {
175214
this.datastore.get(key, (err, res) => {
176215
if (!err && res) {
177216
this.wm.cancelWants([key])
178-
finish(res)
217+
finish(null, res)
179218
return
180219
}
181220

@@ -185,14 +224,19 @@ module.exports = class Bitwap {
185224
})
186225
}
187226
})
188-
this.notifications.once(`block:${key.toString('hex')}`, (block) => {
189-
finish(block)
190-
})
191227
})
192228

193229
this.wm.wantBlocks(keys)
194230
}
195231

232+
// removes the given keys from the want list independent of any ref counts
233+
unwantBlocks (keys) {
234+
this.wm.unwantBlocks(keys)
235+
keys.forEach((key) => {
236+
this.notifications.emit(`unwant:${key.toString('hex')}`)
237+
})
238+
}
239+
196240
// removes the given keys from the want list
197241
cancelWants (keys) {
198242
this.wm.cancelWants(keys)

src/wantlist/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ class Wantlist {
3535
this.set.delete(key.toString('hex'))
3636
}
3737

38+
removeForce (key) {
39+
if (this.set.has(key)) {
40+
this.set.delete(key)
41+
}
42+
}
43+
3844
entries () {
3945
return this.set.entries()
4046
}

src/wantmanager/index.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module.exports = class Wantmanager {
2323
return new MsgQueue(peerId, this.network)
2424
}
2525

26-
_addEntries (keys, cancel) {
26+
_addEntries (keys, cancel, force) {
2727
let i = -1
2828
_(keys)
2929
.map((key) => {
@@ -33,7 +33,11 @@ module.exports = class Wantmanager {
3333
.tap((e) => {
3434
// add changes to our wantlist
3535
if (e.cancel) {
36-
this.wl.remove(e.key)
36+
if (force) {
37+
this.wl.removeForce(e.key)
38+
} else {
39+
this.wl.remove(e.key)
40+
}
3741
} else {
3842
this.wl.add(e.key, e.priority)
3943
}
@@ -90,6 +94,12 @@ module.exports = class Wantmanager {
9094
this._addEntries(keys, false)
9195
}
9296

97+
// remove blocks of all the given keys without respecting refcounts
98+
unwantBlocks (keys) {
99+
log('unwant blocks:', keys)
100+
this._addEntries(keys, true, true)
101+
}
102+
93103
// cancel wanting all of the given keys
94104
cancelWants (keys) {
95105
log('cancel wants: ', keys)

0 commit comments

Comments
 (0)