hypercore 10.0.0-alpha.45 → 10.0.0-alpha.48

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/README.md CHANGED
@@ -66,7 +66,8 @@ Note that `tree`, `data`, and `bitfield` are normally heavily sparse files.
66
66
  valueEncoding: 'json' | 'utf-8' | 'binary', // defaults to binary
67
67
  encodeBatch: batch => { ... }, // optionally apply an encoding to complete batches
68
68
  keyPair: kp, // optionally pass the public key and secret key as a key pair
69
- encryptionKey: k // optionally pass an encryption key to enable block encryption
69
+ encryptionKey: k, // optionally pass an encryption key to enable block encryption
70
+ onwait: () => {} // hook that is called if gets are waiting for download
70
71
  }
71
72
  ```
72
73
 
package/index.js CHANGED
@@ -70,6 +70,7 @@ module.exports = class Hypercore extends EventEmitter {
70
70
  this.sessions = opts._sessions || [this]
71
71
  this.auth = opts.auth || null
72
72
  this.autoClose = !!opts.autoClose
73
+ this.onwait = opts.onwait || null
73
74
 
74
75
  this.closing = null
75
76
  this.opening = this._openSession(key, storage, opts)
@@ -113,6 +114,7 @@ module.exports = class Hypercore extends EventEmitter {
113
114
  indent + ' opened: ' + opts.stylize(this.opened, 'boolean') + '\n' +
114
115
  indent + ' closed: ' + opts.stylize(this.closed, 'boolean') + '\n' +
115
116
  indent + ' snapshotted: ' + opts.stylize(this.snapshotted, 'boolean') + '\n' +
117
+ indent + ' sparse: ' + opts.stylize(this.sparse, 'boolean') + '\n' +
116
118
  indent + ' writable: ' + opts.stylize(this.writable, 'boolean') + '\n' +
117
119
  indent + ' length: ' + opts.stylize(this.length, 'number') + '\n' +
118
120
  indent + ' byteLength: ' + opts.stylize(this.byteLength, 'number') + '\n' +
@@ -182,9 +184,11 @@ module.exports = class Hypercore extends EventEmitter {
182
184
  throw SESSION_CLOSED('Cannot make sessions on a closing core')
183
185
  }
184
186
 
187
+ const sparse = opts.sparse === false ? false : this.sparse
185
188
  const Clz = opts.class || Hypercore
186
189
  const s = new Clz(this.storage, this.key, {
187
190
  ...opts,
191
+ sparse,
188
192
  _opening: this.opening,
189
193
  _sessions: this.sessions
190
194
  })
@@ -324,14 +328,27 @@ module.exports = class Hypercore extends EventEmitter {
324
328
  }
325
329
  }
326
330
 
327
- _updateSnapshot () {
328
- const prev = this._snapshot
329
- const next = this._snapshot = {
330
- length: this.core.tree.length,
331
- byteLength: this.core.tree.byteLength,
331
+ _getSnapshot () {
332
+ if (this.sparse) {
333
+ return {
334
+ length: this.core.tree.length,
335
+ byteLength: this.core.tree.byteLength,
336
+ fork: this.core.tree.fork,
337
+ compatLength: this.core.tree.length
338
+ }
339
+ }
340
+
341
+ return {
342
+ length: this.core.header.contiguousLength,
343
+ byteLength: 0,
332
344
  fork: this.core.tree.fork,
333
- compatLength: this.core.tree.length
345
+ compatLength: this.core.header.contiguousLength
334
346
  }
347
+ }
348
+
349
+ _updateSnapshot () {
350
+ const prev = this._snapshot
351
+ const next = this._snapshot = this._getSnapshot()
335
352
 
336
353
  if (!prev) return true
337
354
  return prev.length !== next.length || prev.fork !== next.fork
@@ -573,10 +590,22 @@ module.exports = class Hypercore extends EventEmitter {
573
590
  const activeRequests = (opts && opts.activeRequests) || this.activeRequests
574
591
  const req = this.replicator.addUpgrade(activeRequests)
575
592
 
576
- if (!this.snapshotted) return req.promise
577
- if (!(await req.promise)) return false
593
+ let upgraded = await req.promise
594
+
595
+ if (!this.sparse) {
596
+ // Download all available blocks in non-sparse mode
597
+ const start = this.length
598
+ const end = this.core.tree.length
599
+ const contig = this.contiguousLength
600
+
601
+ await this.download({ start, end, ifAvailable: true }).downloaded()
602
+
603
+ if (!upgraded) upgraded = this.contiguousLength !== contig
604
+ }
578
605
 
579
- return this._updateSnapshot()
606
+ if (!upgraded) return false
607
+ if (this.snapshotted) return this._updateSnapshot()
608
+ return true
580
609
  }
581
610
 
582
611
  async seek (bytes, opts) {
@@ -634,6 +663,7 @@ module.exports = class Hypercore extends EventEmitter {
634
663
  } else {
635
664
  if (opts && opts.wait === false) return null
636
665
  if (opts && opts.onwait) opts.onwait(index)
666
+ else if (this.onwait) this.onwait(index)
637
667
 
638
668
  const activeRequests = (opts && opts.activeRequests) || this.activeRequests
639
669
 
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/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 } = {}) {
922
+ addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false, ifAvailable = false } = {}) {
913
923
  if (blocks !== null) { // if using blocks, start, end just acts as frames around the blocks array
914
924
  start = 0
915
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.45",
3
+ "version": "10.0.0-alpha.48",
4
4
  "description": "Hypercore 10",
5
5
  "main": "index.js",
6
6
  "scripts": {