hypercore 10.0.0-alpha.43 → 10.0.0-alpha.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -191,8 +191,10 @@ module.exports = class Hypercore extends EventEmitter {
191
191
 
192
192
  s._passCapabilities(this)
193
193
 
194
- // Pass on the cache unless explicitly disabled.
195
- if (opts.cache !== false) s.cache = this.cache
194
+ // Configure the cache unless explicitly disabled.
195
+ if (opts.cache !== false) {
196
+ s.cache = opts.cache === true || !opts.cache ? this.cache : opts.cache
197
+ }
196
198
 
197
199
  ensureEncryption(s, opts)
198
200
 
@@ -295,7 +297,8 @@ module.exports = class Hypercore extends EventEmitter {
295
297
  crypto: this.crypto,
296
298
  legacy: opts.legacy,
297
299
  auth: opts.auth,
298
- onupdate: this._oncoreupdate.bind(this)
300
+ onupdate: this._oncoreupdate.bind(this),
301
+ oncontigupdate: this._oncorecontigupdate.bind(this)
299
302
  })
300
303
 
301
304
  if (opts.userData) {
@@ -482,9 +485,10 @@ module.exports = class Hypercore extends EventEmitter {
482
485
  if (s._snapshot && bitfield.start < s._snapshot.compatLength) s._snapshot.compatLength = bitfield.start
483
486
  }
484
487
 
485
- if (appended) {
486
- s.emit('append')
487
- }
488
+ // For sparse sessions, immediately emit appends. Non-sparse sessions
489
+ // are handled separately and only emit appends when their contiguous
490
+ // length is updated.
491
+ if (appended && s.sparse) s.emit('append')
488
492
  }
489
493
 
490
494
  this.replicator.onupgrade()
@@ -503,6 +507,16 @@ module.exports = class Hypercore extends EventEmitter {
503
507
  }
504
508
  }
505
509
 
510
+ _oncorecontigupdate () {
511
+ // For non-sparse sessions, emit appends only when the contiguous length is
512
+ // updated.
513
+ for (let i = 0; i < this.sessions.length; i++) {
514
+ const s = this.sessions[i]
515
+
516
+ if (!s.sparse) s.emit('append')
517
+ }
518
+ }
519
+
506
520
  _onpeerupdate (added, peer) {
507
521
  const name = added ? 'peer-add' : 'peer-remove'
508
522
 
@@ -559,10 +573,19 @@ module.exports = class Hypercore extends EventEmitter {
559
573
  const activeRequests = (opts && opts.activeRequests) || this.activeRequests
560
574
  const req = this.replicator.addUpgrade(activeRequests)
561
575
 
562
- if (!this.snapshotted) return req.promise
563
- if (!(await req.promise)) return false
576
+ const upgraded = await req.promise
577
+
578
+ if (!this.sparse) {
579
+ // Download all available blocks in non-sparse mode
580
+ const start = this.length
581
+ const end = this.core.tree.length
582
+
583
+ await this.download({ start, end, ifAvailable: true }).downloaded()
584
+ }
564
585
 
565
- return this._updateSnapshot()
586
+ if (!upgraded) return false
587
+ if (this.snapshotted) return this._updateSnapshot()
588
+ return true
566
589
  }
567
590
 
568
591
  async seek (bytes, opts) {
package/lib/caps.js CHANGED
@@ -4,9 +4,7 @@ const b4a = require('b4a')
4
4
  const c = require('compact-encoding')
5
5
 
6
6
  // TODO: rename this to "crypto" and move everything hashing related etc in here
7
- // Also lets move the tree stuff from hypercore-crypto here, and loose the types
8
- // from the hashes there - they are not needed since we lock the indexes in the tree
9
- // hash and just makes alignment etc harder in other languages
7
+ // Also lets move the tree stuff from hypercore-crypto here
10
8
 
11
9
  const [TREE, REPLICATE_INITIATOR, REPLICATE_RESPONDER] = crypto.namespace('hypercore', 3)
12
10
 
package/lib/core.js CHANGED
@@ -9,8 +9,9 @@ const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_SIGNATURE } = req
9
9
  const m = require('./messages')
10
10
 
11
11
  module.exports = class Core {
12
- constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate) {
12
+ constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate, oncontigupdate) {
13
13
  this.onupdate = onupdate
14
+ this.oncontigupdate = oncontigupdate
14
15
  this.header = header
15
16
  this.crypto = crypto
16
17
  this.oplog = oplog
@@ -164,7 +165,7 @@ module.exports = class Core {
164
165
  }
165
166
  }
166
167
 
167
- return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop)
168
+ return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop, opts.oncontigupdate || noop)
168
169
  }
169
170
 
170
171
  _shouldFlush () {
@@ -202,6 +203,7 @@ module.exports = class Core {
202
203
  while (this.bitfield.get(i)) i++
203
204
 
204
205
  this.header.contiguousLength = i
206
+ this.oncontigupdate()
205
207
  }
206
208
  }
207
209
 
@@ -285,6 +287,7 @@ module.exports = class Core {
285
287
  batch.commit()
286
288
 
287
289
  this.header.contiguousLength = batch.length
290
+ this.oncontigupdate()
288
291
  this.header.tree.length = batch.length
289
292
  this.header.tree.rootHash = hash
290
293
  this.header.tree.signature = batch.signature
@@ -472,6 +475,7 @@ module.exports = class Core {
472
475
  const appended = batch.length > batch.ancestors
473
476
 
474
477
  this.header.contiguousLength = Math.min(batch.ancestors, this.header.contiguousLength)
478
+ this.oncontigupdate()
475
479
  this.header.tree.fork = batch.fork
476
480
  this.header.tree.length = batch.length
477
481
  this.header.tree.rootHash = batch.hash()
package/lib/replicator.js CHANGED
@@ -102,12 +102,13 @@ class BlockRequest extends Attachable {
102
102
  }
103
103
 
104
104
  class RangeRequest extends Attachable {
105
- constructor (ranges, start, end, linear, blocks) {
105
+ constructor (ranges, start, end, linear, ifAvailable, blocks) {
106
106
  super()
107
107
 
108
108
  this.start = start
109
109
  this.end = end
110
110
  this.linear = linear
111
+ this.ifAvailable = ifAvailable
111
112
  this.blocks = blocks
112
113
  this.ranges = ranges
113
114
 
@@ -172,6 +173,10 @@ class InflightTracker {
172
173
  this._free = []
173
174
  }
174
175
 
176
+ get idle () {
177
+ return this._requests.length === this._free.length
178
+ }
179
+
175
180
  * [Symbol.iterator] () {
176
181
  for (const req of this._requests) {
177
182
  if (req !== null) yield req
@@ -260,6 +265,7 @@ class Peer {
260
265
 
261
266
  this.inflight = 0
262
267
  this.maxInflight = DEFAULT_MAX_INFLIGHT
268
+ this.dataProcessing = 0
263
269
 
264
270
  this.canUpgrade = true
265
271
 
@@ -515,6 +521,8 @@ class Peer {
515
521
 
516
522
  if (reorg === true) return this.replicator._onreorgdata(this, req, data)
517
523
 
524
+ this.dataProcessing++
525
+
518
526
  try {
519
527
  if (!matchingRequest(req, data) || !(await this.core.verify(data, this))) {
520
528
  this.replicator._onnodata(this, req)
@@ -523,6 +531,8 @@ class Peer {
523
531
  } catch (err) {
524
532
  this.replicator._onnodata(this, req)
525
533
  throw err
534
+ } finally {
535
+ this.dataProcessing--
526
536
  }
527
537
 
528
538
  this.replicator._ondata(this, req, data)
@@ -909,13 +919,21 @@ module.exports = class Replicator {
909
919
  return ref
910
920
  }
911
921
 
912
- addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false } = {}) {
913
- if (blocks !== null) {
914
- if (start >= blocks.length) start = blocks.length
915
- if (length === -1 || start + length > blocks.length) length = blocks.length - start
922
+ addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false, ifAvailable = false } = {}) {
923
+ if (blocks !== null) { // if using blocks, start, end just acts as frames around the blocks array
924
+ start = 0
925
+ end = length = blocks.length
916
926
  }
917
927
 
918
- const r = new RangeRequest(this._ranges, start, length === -1 ? -1 : start + length, linear, blocks)
928
+ const r = new RangeRequest(
929
+ this._ranges,
930
+ start,
931
+ length === -1 ? -1 : start + length,
932
+ linear,
933
+ ifAvailable,
934
+ blocks
935
+ )
936
+
919
937
  const ref = r.attach(session)
920
938
 
921
939
  this._ranges.push(r)
@@ -1115,6 +1133,14 @@ module.exports = class Replicator {
1115
1133
  return true
1116
1134
  }
1117
1135
 
1136
+ _resolveRangeRequest (req, index) {
1137
+ const head = this._ranges.pop()
1138
+
1139
+ if (index < this._ranges.length) this._ranges[index] = head
1140
+
1141
+ req.resolve(true)
1142
+ }
1143
+
1118
1144
  _clearInflightBlock (tracker, req) {
1119
1145
  const isBlock = tracker === this._blocks
1120
1146
  const index = isBlock === true ? req.block.index : req.hash.index / 2
@@ -1168,14 +1194,9 @@ module.exports = class Replicator {
1168
1194
  while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.start)) === true) r.start++
1169
1195
  while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.end - 1)) === true) r.end--
1170
1196
 
1171
- if (r.end === -1 || r.start < r.end) continue
1172
-
1173
- if (i < this._ranges.length - 1) this._ranges[i] = this._ranges.pop()
1174
- else this._ranges.pop()
1175
-
1176
- i--
1177
-
1178
- r.resolve(true)
1197
+ if (r.end !== -1 && r.start >= r.end) {
1198
+ this._resolveRangeRequest(r, i--)
1199
+ }
1179
1200
  }
1180
1201
 
1181
1202
  for (let i = 0; i < this._seeks.length; i++) {
@@ -1201,7 +1222,7 @@ module.exports = class Replicator {
1201
1222
  else s.resolve(res)
1202
1223
  }
1203
1224
 
1204
- this.updateAll()
1225
+ if (this._inflight.idle) this.updateAll()
1205
1226
 
1206
1227
  // No additional updates scheduled - return
1207
1228
  if (--this._updatesPending === 0) return
@@ -1210,6 +1231,22 @@ module.exports = class Replicator {
1210
1231
  }
1211
1232
  }
1212
1233
 
1234
+ _maybeResolveIfAvailableRanges () {
1235
+ if (this._ifAvailable > 0 || !this._inflight.idle || !this._ranges.length) return
1236
+
1237
+ for (let i = 0; i < this.peers.length; i++) {
1238
+ if (this.peers[i].dataProcessing > 0) return
1239
+ }
1240
+
1241
+ for (let i = 0; i < this._ranges.length; i++) {
1242
+ const r = this._ranges[i]
1243
+
1244
+ if (r.ifAvailable) {
1245
+ this._resolveRangeRequest(r, i--)
1246
+ }
1247
+ }
1248
+ }
1249
+
1213
1250
  _clearRequest (peer, req) {
1214
1251
  if (req.block !== null) {
1215
1252
  this._clearInflightBlock(this._blocks, req)
@@ -1407,6 +1444,7 @@ module.exports = class Replicator {
1407
1444
  while (this._updatePeerNonPrimary(peer) === true);
1408
1445
 
1409
1446
  this._checkUpgradeIfAvailable()
1447
+ this._maybeResolveIfAvailableRanges()
1410
1448
  }
1411
1449
 
1412
1450
  updateAll () {
@@ -1434,6 +1472,7 @@ module.exports = class Replicator {
1434
1472
  }
1435
1473
 
1436
1474
  this._checkUpgradeIfAvailable()
1475
+ this._maybeResolveIfAvailableRanges()
1437
1476
  }
1438
1477
 
1439
1478
  attachTo (protomux) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "10.0.0-alpha.43",
3
+ "version": "10.0.0-alpha.46",
4
4
  "description": "Hypercore 10",
5
5
  "main": "index.js",
6
6
  "scripts": {