hyperbee2 2.3.0 → 2.4.2

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
@@ -6,6 +6,7 @@ const { ChangesStream } = require('./lib/changes.js')
6
6
  const NodeCache = require('./lib/cache.js')
7
7
  const WriteBatch = require('./lib/write.js')
8
8
  const CoreContext = require('./lib/context.js')
9
+ const SessionConfig = require('./lib/session-config.js')
9
10
  const { Pointer, KeyPointer, ValuePointer, TreeNode, EMPTY } = require('./lib/tree.js')
10
11
  const { DeltaOp, DeltaCohort, OP_COHORT } = require('./lib/compression.js')
11
12
 
@@ -16,10 +17,13 @@ class Hyperbee {
16
17
  key = null,
17
18
  encryption = null,
18
19
  maxCacheSize = 4096,
20
+ config = new SessionConfig([], 0, true),
21
+ activeRequests = config.activeRequests,
22
+ timeout = config.timeout,
23
+ wait = config.wait,
19
24
  core = key ? store.get(key) : store.get({ key, name: 'bee', encryption }),
20
25
  context = new CoreContext(store, core, new NodeCache(maxCacheSize), core, encryption, t),
21
26
  root = null,
22
- activeRequests = [],
23
27
  view = false,
24
28
  writable = true,
25
29
  unbatch = 0,
@@ -29,7 +33,7 @@ class Hyperbee {
29
33
  this.store = store
30
34
  this.root = root
31
35
  this.context = context
32
- this.activeRequests = activeRequests
36
+ this.config = config.sub(activeRequests, timeout, wait)
33
37
  this.view = view
34
38
  this.writable = writable
35
39
  this.unbatch = unbatch
@@ -79,6 +83,8 @@ class Hyperbee {
79
83
 
80
84
  _makeView(context, root, writable, unbatch) {
81
85
  return new Hyperbee(this.store, {
86
+ config: this.config,
87
+ core: context.core,
82
88
  context,
83
89
  root,
84
90
  view: true,
@@ -123,7 +129,7 @@ class Hyperbee {
123
129
  }
124
130
 
125
131
  async close() {
126
- if (this.activeRequests.length) Hypercore.clearRequests(this.activeRequests)
132
+ if (this.config.activeRequests.length) Hypercore.clearRequests(this.config.activeRequests)
127
133
  if (!this.view) await this.store.close()
128
134
  }
129
135
 
@@ -163,15 +169,15 @@ class Hyperbee {
163
169
  }
164
170
 
165
171
  // TODO: unslab these
166
- async inflate(ptr, activeRequests = this.activeRequests) {
172
+ async inflate(ptr, config) {
167
173
  if (ptr.value) {
168
174
  this.bump(ptr)
169
175
  return ptr.value
170
176
  }
171
177
 
172
178
  const [block, context] = await Promise.all([
173
- ptr.context.getBlock(ptr.seq, ptr.core, activeRequests),
174
- ptr.context.getContext(ptr.core, activeRequests)
179
+ ptr.context.getBlock(ptr.seq, ptr.core, config),
180
+ ptr.context.getContext(ptr.core, config)
175
181
  ])
176
182
 
177
183
  const tree = block.tree[ptr.offset]
@@ -181,15 +187,17 @@ class Hyperbee {
181
187
 
182
188
  for (let i = 0; i < keys.length; i++) {
183
189
  const d = tree.keys[i]
184
- keys[i] = inflateKey(context, d, ptr, block, activeRequests)
190
+ keys[i] = inflateKey(context, d, ptr, block, config)
185
191
  }
186
192
 
187
193
  for (let i = 0; i < children.length; i++) {
188
194
  const d = tree.children[i]
189
- children[i] = inflateChild(context, d, ptr, block, activeRequests)
195
+ children[i] = inflateChild(context, d, ptr, block, config)
190
196
  }
191
197
 
192
- const value = new TreeNode(await Promise.all(keys), await Promise.all(children))
198
+ const [k, c] = await Promise.all([Promise.all(keys), Promise.all(children)])
199
+
200
+ const value = new TreeNode(k, c)
193
201
  if (!ptr.value) ptr.value = value
194
202
 
195
203
  this.bump(ptr)
@@ -197,8 +205,8 @@ class Hyperbee {
197
205
  return ptr.value
198
206
  }
199
207
 
200
- async finalizeKeyPointer(key, activeRequests = this.activeRequests) {
201
- const value = key.value || (await this.inflateValue(key, activeRequests))
208
+ async finalizeKeyPointer(key, config) {
209
+ const value = key.value || (await this.inflateValue(key, config))
202
210
 
203
211
  return {
204
212
  core: key.context.getCore(key.core),
@@ -209,20 +217,20 @@ class Hyperbee {
209
217
  }
210
218
  }
211
219
 
212
- async inflateValue(key, activeRequests = this.activeRequests) {
220
+ async inflateValue(key, config) {
213
221
  if (key.value) return key.value
214
222
  if (!key.valuePointer) return null
215
223
 
216
224
  const ptr = key.valuePointer
217
225
 
218
226
  if (ptr.split === 0) {
219
- const block = await ptr.context.getBlock(ptr.seq, ptr.core, activeRequests)
227
+ const block = await ptr.context.getBlock(ptr.seq, ptr.core, config)
220
228
  return block.values[ptr.offset]
221
229
  }
222
230
 
223
231
  const blockPromises = new Array(ptr.split + 1)
224
232
  for (let i = 0; i < blockPromises.length; i++) {
225
- blockPromises[i] = ptr.context.getBlock(ptr.seq - ptr.split + i, ptr.core, activeRequests)
233
+ blockPromises[i] = ptr.context.getBlock(ptr.seq - ptr.split + i, ptr.core, config)
226
234
  }
227
235
  const blocks = await Promise.all(blockPromises)
228
236
  const splitValue = new Array(blockPromises.length)
@@ -233,13 +241,13 @@ class Hyperbee {
233
241
  return b4a.concat(splitValue)
234
242
  }
235
243
 
236
- async bootstrap(activeRequests = this.activeRequests) {
244
+ async bootstrap(config) {
237
245
  if (!this.root) await this.ready()
238
- if (this.unbatch) await this._rollback(activeRequests)
246
+ if (this.unbatch) await this._rollback(config)
239
247
  return this.root === EMPTY ? null : this.root
240
248
  }
241
249
 
242
- async _rollback(activeRequests) {
250
+ async _rollback(config) {
243
251
  const expected = this.unbatch
244
252
 
245
253
  let n = expected
@@ -248,14 +256,14 @@ class Hyperbee {
248
256
 
249
257
  while (n > 0 && length > 0 && expected === this.unbatch) {
250
258
  const seq = length - 1
251
- const blk = await context.getBlock(seq, 0, activeRequests)
259
+ const blk = await context.getBlock(seq, 0, config)
252
260
 
253
261
  if (!blk.previous) {
254
262
  length = 0
255
263
  break
256
264
  }
257
265
 
258
- context = await context.getContext(blk.previous.core, activeRequests)
266
+ context = await context.getContext(blk.previous.core, config)
259
267
  length = blk.previous.seq + 1
260
268
  n--
261
269
  }
@@ -272,12 +280,14 @@ class Hyperbee {
272
280
  this.unbatch = 0
273
281
  }
274
282
 
275
- async get(key, { activeRequests = this.activeRequests } = {}) {
276
- let ptr = await this.bootstrap(activeRequests)
283
+ async get(key, opts) {
284
+ const config = this.config.options(opts)
285
+
286
+ let ptr = await this.bootstrap(config)
277
287
  if (!ptr) return null
278
288
 
279
289
  while (true) {
280
- const v = ptr.value ? this.bump(ptr) : await this.inflate(ptr, activeRequests)
290
+ const v = ptr.value ? this.bump(ptr) : await this.inflate(ptr, config)
281
291
 
282
292
  let s = 0
283
293
  let e = v.keys.length
@@ -289,7 +299,7 @@ class Hyperbee {
289
299
 
290
300
  c = b4a.compare(key, m.key)
291
301
 
292
- if (c === 0) return this.finalizeKeyPointer(m, activeRequests)
302
+ if (c === 0) return this.finalizeKeyPointer(m, config)
293
303
 
294
304
  if (c < 0) e = mid
295
305
  else s = mid + 1
@@ -307,12 +317,12 @@ module.exports = Hyperbee
307
317
 
308
318
  function noop() {}
309
319
 
310
- function inflateKey(context, d, ptr, block, activeRequests) {
311
- if (d.type === OP_COHORT) return inflateKeyCohort(context, d, ptr, block, activeRequests)
312
- return inflateKeyDelta(context, d, ptr, block, activeRequests)
320
+ function inflateKey(context, d, ptr, block, config) {
321
+ if (d.type === OP_COHORT) return inflateKeyCohort(context, d, ptr, block, config)
322
+ return inflateKeyDelta(context, d, ptr, block, config)
313
323
  }
314
324
 
315
- async function inflateKeyDelta(context, d, ptr, block, activeRequests) {
325
+ async function inflateKeyDelta(context, d, ptr, block, config) {
316
326
  const k = d.pointer
317
327
 
318
328
  if (!k) return new DeltaOp(false, d.type, d.index, null)
@@ -320,7 +330,7 @@ async function inflateKeyDelta(context, d, ptr, block, activeRequests) {
320
330
  const blk =
321
331
  k.seq === ptr.seq && k.core === 0 && ptr.core === 0
322
332
  ? block
323
- : await context.getBlock(k.seq, k.core, activeRequests)
333
+ : await context.getBlock(k.seq, k.core, config)
324
334
 
325
335
  const bk = blk.keys[k.offset]
326
336
 
@@ -328,7 +338,7 @@ async function inflateKeyDelta(context, d, ptr, block, activeRequests) {
328
338
 
329
339
  if (bk.valuePointer) {
330
340
  const p = bk.valuePointer
331
- const ctx = await context.getContext(k.core, activeRequests)
341
+ const ctx = await context.getContext(k.core, config)
332
342
  vp = new ValuePointer(ctx, p.core, p.seq, p.offset, p.split)
333
343
  }
334
344
 
@@ -336,20 +346,20 @@ async function inflateKeyDelta(context, d, ptr, block, activeRequests) {
336
346
  return new DeltaOp(false, d.type, d.index, kp)
337
347
  }
338
348
 
339
- async function inflateKeyCohort(context, d, ptr, block, activeRequests) {
349
+ async function inflateKeyCohort(context, d, ptr, block, config) {
340
350
  const co = d.pointer
341
351
 
342
352
  const blk =
343
353
  co.seq === ptr.seq && co.core === 0 && ptr.core === 0
344
354
  ? block
345
- : await context.getBlock(co.seq, co.core, activeRequests)
355
+ : await context.getBlock(co.seq, co.core, config)
346
356
 
347
357
  const cohort = blk.cohorts[co.offset]
348
358
  const promises = new Array(cohort.length)
349
359
 
350
360
  for (let i = 0; i < cohort.length; i++) {
351
361
  const p = cohort[i]
352
- const k = inflateKeyDelta(context, p, co, blk, activeRequests)
362
+ const k = inflateKeyDelta(context, p, co, blk, config)
353
363
  promises[i] = k
354
364
  }
355
365
 
@@ -357,31 +367,31 @@ async function inflateKeyCohort(context, d, ptr, block, activeRequests) {
357
367
  return new DeltaCohort(false, p, await Promise.all(promises))
358
368
  }
359
369
 
360
- function inflateChild(context, d, ptr, block, activeRequests) {
361
- if (d.type === OP_COHORT) return inflateChildCohort(context, d, ptr, block, activeRequests)
362
- return Promise.resolve(inflateChildDelta(context, d, ptr, block, activeRequests))
370
+ function inflateChild(context, d, ptr, block, config) {
371
+ if (d.type === OP_COHORT) return inflateChildCohort(context, d, ptr, block, config)
372
+ return Promise.resolve(inflateChildDelta(context, d, ptr, block, config))
363
373
  }
364
374
 
365
- function inflateChildDelta(context, d, ptr, block, activeRequests) {
375
+ function inflateChildDelta(context, d, ptr, block, config) {
366
376
  const p = d.pointer
367
377
  const c = p && context.createTreeNode(p.core, p.seq, p.offset, false, null)
368
378
  return new DeltaOp(false, d.type, d.index, c)
369
379
  }
370
380
 
371
- async function inflateChildCohort(context, d, ptr, block, activeRequests) {
381
+ async function inflateChildCohort(context, d, ptr, block, config) {
372
382
  const co = d.pointer
373
383
 
374
384
  const blk =
375
385
  co.seq === ptr.seq && co.core === 0 && ptr.core === 0
376
386
  ? block
377
- : await context.getBlock(co.seq, co.core, activeRequests)
387
+ : await context.getBlock(co.seq, co.core, config)
378
388
 
379
389
  const cohort = blk.cohorts[co.offset]
380
390
  const deltas = new Array(cohort.length)
381
391
 
382
392
  for (let i = 0; i < cohort.length; i++) {
383
393
  const c = cohort[i]
384
- deltas[i] = inflateChildDelta(context, c, co, blk, activeRequests)
394
+ deltas[i] = inflateChildDelta(context, c, co, blk, config)
385
395
  }
386
396
 
387
397
  const p = new Pointer(context, co.core, co.seq, co.offset)
package/lib/changes.js CHANGED
@@ -1,43 +1,41 @@
1
1
  const { Readable } = require('streamx')
2
2
 
3
3
  class ChangesStream extends Readable {
4
- constructor(tree, options = {}) {
5
- const { highWaterMark } = options
4
+ constructor(tree, opts = {}) {
5
+ const { highWaterMark, head = null } = opts
6
6
  super({ eagerOpen: true, highWaterMark })
7
7
 
8
- const { head = null, activeRequests = tree.activeRequests } = options
9
-
10
8
  this.tree = tree
11
9
 
12
- this._head = head
13
- this._context = null
14
- this._activeRequests = activeRequests
10
+ this.head = head
11
+ this.context = null
12
+ this.config = tree.config.options(opts)
15
13
  }
16
14
 
17
15
  async _openp() {
18
- await this.tree.bootstrap(this._activeRequests)
19
- if (this._head === null) this._head = this.tree.head()
20
- if (this._head !== null) this._context = this.tree.context.getContextByKey(this._head.key)
16
+ await this.tree.bootstrap(this.config)
17
+ if (this.head === null) this.head = this.tree.head()
18
+ if (this.head !== null) this.context = this.tree.context.getContextByKey(this.head.key)
21
19
  }
22
20
 
23
21
  async _readp() {
24
- if (!this._context || this._head.length === 0) {
22
+ if (!this.context || this.head.length === 0) {
25
23
  this.push(null)
26
24
  return
27
25
  }
28
26
 
29
27
  const data = {
30
- head: this._head,
28
+ head: this.head,
31
29
  batch: []
32
30
  }
33
31
 
34
- const seq = this._head.length - 1
35
- const blk = await this._context.getBlock(seq, 0, this._activeRequests)
32
+ const seq = this.head.length - 1
33
+ const blk = await this.context.getBlock(seq, 0, this.config)
36
34
  const batchStart = seq - blk.batch.start
37
35
  const remaining = new Array(blk.batch.start)
38
36
 
39
37
  for (let i = 0; i < remaining.length; i++) {
40
- remaining[i] = this._context.getBlock(batchStart + i, 0, this._activeRequests)
38
+ remaining[i] = this.context.getBlock(batchStart + i, 0, this.config)
41
39
  }
42
40
 
43
41
  for (const blk of await Promise.all(remaining)) data.batch.push(blk)
@@ -46,13 +44,13 @@ class ChangesStream extends Readable {
46
44
  this.push(data)
47
45
 
48
46
  if (!blk.previous) {
49
- this._head = null
50
- this._context = null
47
+ this.head = null
48
+ this.context = null
51
49
  return
52
50
  }
53
51
 
54
- this._context = await this._context.getContext(blk.previous.core, this._activeRequests)
55
- this._head = { key: this._context.core.key, length: blk.previous.seq + 1 }
52
+ this.context = await this.context.getContext(blk.previous.core, this.config)
53
+ this.head = { key: this.context.core.key, length: blk.previous.seq + 1 }
56
54
  }
57
55
 
58
56
  async _open(cb) {
package/lib/context.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const b4a = require('b4a')
2
2
  const ScopeLock = require('scope-lock')
3
+ const { BLOCK_NOT_AVAILABLE } = require('hypercore-errors')
3
4
  const { TreeNodePointer } = require('./tree.js')
4
5
  const { decodeBlock } = require('./encoding.js')
5
6
 
@@ -27,20 +28,26 @@ class CoreContext {
27
28
  // return '[CoreContext]'
28
29
  // }
29
30
 
30
- async update(activeRequests) {
31
+ async update(config) {
31
32
  await this.core.ready()
32
33
 
33
34
  if (this.length === this.core.length || this.core.length === 0) return
34
35
 
35
36
  const length = this.core.length
36
37
  const seq = length - 1
37
- const buffer = await this.core.get(seq, { activeRequests })
38
+ const buffer = await this.core.get(seq, config)
38
39
  const block = decodeBlock(buffer, seq)
40
+
41
+ await this._inflateCheckpoint(length, block, config)
42
+ }
43
+
44
+ async _inflateCheckpoint(length, block, config) {
39
45
  const checkpoint = block.checkpoint
40
46
 
41
47
  if (checkpoint > 0) {
42
- const buffer = await this.core.get(checkpoint - 1)
43
- const block = decodeBlock(buffer, checkpoint - 1)
48
+ const seq = checkpoint - 1
49
+ const buffer = await this.core.get(seq, config)
50
+ const block = decodeBlock(buffer, seq)
44
51
 
45
52
  if (length < this.length) return
46
53
 
@@ -84,12 +91,12 @@ class CoreContext {
84
91
  return this.cores.length
85
92
  }
86
93
 
87
- async getCoreOffset(context, core, activeRequests) {
88
- if (core !== 0 && core - 1 >= context.cores.length) await context.update(activeRequests)
94
+ async getCoreOffset(context, core, config) {
95
+ if (core !== 0 && core - 1 >= context.cores.length) await context.update(config)
89
96
  return this.getCoreOffsetLocal(context, core)
90
97
  }
91
98
 
92
- async getCoreOffsetByKey(key, activeRequests) {
99
+ async getCoreOffsetByKey(key, config) {
93
100
  await this.core.ready()
94
101
 
95
102
  if (b4a.equals(key, this.core.key)) return 0
@@ -101,7 +108,7 @@ class CoreContext {
101
108
  }
102
109
  }
103
110
 
104
- await this.update(activeRequests)
111
+ await this.update(config)
105
112
 
106
113
  for (let i = 0; i < this.cores.length; i++) {
107
114
  const k = this.cores[i].key
@@ -135,11 +142,18 @@ class CoreContext {
135
142
  return this.cores[index - 1].key
136
143
  }
137
144
 
138
- async getBlock(seq, core, activeRequests) {
139
- if (core !== 0 && core - 1 >= this.cores.length) await this.update(activeRequests)
145
+ async getBlock(seq, core, config) {
146
+ if (core !== 0 && core - 1 >= this.cores.length) await this.update(config)
147
+
140
148
  const hc = this.getCore(core)
141
- const buffer = await hc.get(seq, { activeRequests })
149
+ const buffer = await hc.get(seq, config)
150
+ if (buffer === null) throw BLOCK_NOT_AVAILABLE()
142
151
  const block = decodeBlock(buffer, seq)
152
+
153
+ if (block.checkpoint > this.checkpoint) {
154
+ await this._inflateCheckpoint(seq + 1, block, config)
155
+ }
156
+
143
157
  return block
144
158
  }
145
159
 
@@ -158,9 +172,9 @@ class CoreContext {
158
172
  return ctx
159
173
  }
160
174
 
161
- async getContext(core, activeRequests) {
175
+ async getContext(core, config) {
162
176
  if (core === 0) return this
163
- if (core > this.cores.length) await this.update(activeRequests)
177
+ if (core > this.cores.length) await this.update(config)
164
178
  if (core > this.cores.length) throw new Error('Bad core index: ' + core)
165
179
 
166
180
  const hex = b4a.toString(this.cores[core - 1].key, 'hex')
package/lib/diff.js CHANGED
@@ -3,7 +3,9 @@ const b4a = require('b4a')
3
3
  const { RangeIterator } = require('./ranges.js')
4
4
 
5
5
  class DiffIterator {
6
- constructor(tree, left, right, { limit = -1, activeRequests = [] } = {}) {
6
+ constructor(tree, left, right, opts = {}) {
7
+ const { limit = -1 } = opts
8
+
7
9
  this.tree = tree
8
10
 
9
11
  this.left = left
@@ -11,7 +13,7 @@ class DiffIterator {
11
13
 
12
14
  this.left.limit = this.right.limit = -1
13
15
 
14
- this.activeRequests = activeRequests
16
+ this.config = tree.config.options(opts)
15
17
  this.limit = limit
16
18
 
17
19
  this.nextLeft = null
@@ -23,14 +25,14 @@ class DiffIterator {
23
25
  }
24
26
 
25
27
  async _shiftRight() {
26
- const right = await this.tree.finalizeKeyPointer(this.nextRight, this.activeRequests)
28
+ const right = await this.tree.finalizeKeyPointer(this.nextRight, this.config)
27
29
  this.nextRight = null
28
30
  if (this.limit > 0) this.limit--
29
31
  return { left: null, right }
30
32
  }
31
33
 
32
34
  async _shiftLeft() {
33
- const left = await this.tree.finalizeKeyPointer(this.nextLeft, this.activeRequests)
35
+ const left = await this.tree.finalizeKeyPointer(this.nextLeft, this.config)
34
36
  this.nextLeft = null
35
37
  if (this.limit > 0) this.limit--
36
38
  return { left, right: null }
@@ -77,8 +79,8 @@ class DiffIterator {
77
79
  }
78
80
 
79
81
  const [left, right] = await Promise.all([
80
- this.tree.finalizeKeyPointer(leftKey, this.activeRequests),
81
- this.tree.finalizeKeyPointer(rightKey, this.activeRequests)
82
+ this.tree.finalizeKeyPointer(leftKey, this.config),
83
+ this.tree.finalizeKeyPointer(rightKey, this.config)
82
84
  ])
83
85
 
84
86
  if (this.limit > 0) this.limit--
package/lib/ranges.js CHANGED
@@ -3,21 +3,12 @@ const b4a = require('b4a')
3
3
 
4
4
  class RangeIterator {
5
5
  constructor(tree, opts = {}) {
6
- const {
7
- activeRequests = [],
8
- prefetch = true,
9
- reverse = false,
10
- limit = -1,
11
- gte,
12
- gt,
13
- lte,
14
- lt
15
- } = opts
6
+ const { prefetch = true, reverse = false, limit = -1, gte, gt, lte, lt } = opts
16
7
 
17
8
  this.tree = tree
18
9
  this.root = null
19
10
  this.stack = []
20
- this.activeRequests = activeRequests
11
+ this.config = tree.config.options(opts)
21
12
  this.reverse = reverse
22
13
  this.limit = limit
23
14
  this.start = gte || gt || null
@@ -29,7 +20,7 @@ class RangeIterator {
29
20
  }
30
21
 
31
22
  async open() {
32
- if (!this.root) this.root = await this.tree.bootstrap(this.activeRequests)
23
+ if (!this.root) this.root = await this.tree.bootstrap(this.config)
33
24
  if (!this.root) return
34
25
 
35
26
  if (this.limit === 0) return
@@ -44,7 +35,7 @@ class RangeIterator {
44
35
  const top = this.stack[this.stack.length - 1]
45
36
  const v = top.node.value
46
37
  ? this.tree.bump(top.node)
47
- : await this.tree.inflate(top.node, this.activeRequests)
38
+ : await this.tree.inflate(top.node, this.config)
48
39
 
49
40
  for (let i = 0; i < v.keys.length; i++) {
50
41
  const j = this.reverse ? v.keys.length - 1 - i : i
@@ -75,7 +66,7 @@ class RangeIterator {
75
66
 
76
67
  async next() {
77
68
  const key = await this.nextKey()
78
- return key === null ? key : this.tree.finalizeKeyPointer(key, this.activeRequests)
69
+ return key === null ? key : this.tree.finalizeKeyPointer(key, this.config)
79
70
  }
80
71
 
81
72
  async nextKey() {
@@ -83,7 +74,7 @@ class RangeIterator {
83
74
  const top = this.stack.pop()
84
75
  const v = top.node.value
85
76
  ? this.tree.bump(top.node)
86
- : await this.tree.inflate(top.node, this.activeRequests)
77
+ : await this.tree.inflate(top.node, this.config)
87
78
 
88
79
  const offset = top.offset++
89
80
  const child = (offset & 1) === 0
@@ -150,7 +141,7 @@ class RangeIterator {
150
141
  if (cmp > this.compare) break
151
142
 
152
143
  const c = pv.children.get(i)
153
- if (!c.value) this.tree.inflate(c, this.activeRequests).catch(noop)
144
+ if (!c.value) this.tree.inflate(c, this.config).catch(noop)
154
145
 
155
146
  limit = Math.max(limit - this.tree.context.minKeys, 0)
156
147
  if (limit === 0) break
@@ -0,0 +1,23 @@
1
+ class SessionConfig {
2
+ constructor(activeRequests, timeout, wait) {
3
+ this.activeRequests = activeRequests
4
+ this.timeout = timeout
5
+ this.wait = wait
6
+ }
7
+
8
+ sub(activeRequests, timeout, wait) {
9
+ if (this.activeRequests === activeRequests && this.timeout === timeout && this.wait === wait) {
10
+ return this
11
+ }
12
+
13
+ return new SessionConfig(activeRequests, timeout, wait)
14
+ }
15
+
16
+ options(opts) {
17
+ if (!opts) return this
18
+ const { activeRequests = this.activeRequests, timeout = this.timeout, wait = this.wait } = opts
19
+ return this.sub(activeRequests, timeout, wait)
20
+ }
21
+ }
22
+
23
+ module.exports = SessionConfig
package/lib/write.js CHANGED
@@ -23,6 +23,7 @@ module.exports = class WriteBatch {
23
23
  } = opts
24
24
 
25
25
  this.tree = tree
26
+ this.config = tree.config.options(opts)
26
27
  this.deltaMax = deltaMax
27
28
  this.deltaMin = deltaMin
28
29
  this.inlineValueSize = inlineValueSize
@@ -68,7 +69,7 @@ module.exports = class WriteBatch {
68
69
  try {
69
70
  const ops = this.ops
70
71
 
71
- const root = await this.tree.bootstrap()
72
+ const root = await this.tree.bootstrap(this.config)
72
73
 
73
74
  const length = this._getLength(root)
74
75
  const context = this._getContext(root)
@@ -106,11 +107,12 @@ module.exports = class WriteBatch {
106
107
  const stack = []
107
108
  const target = key
108
109
  const snap = this.snapshot
110
+ const conf = this.config
109
111
 
110
112
  let ptr = this.root
111
113
 
112
114
  while (true) {
113
- const v = await retainAndInflate(ptr, snap)
115
+ const v = await retainAndInflate(ptr, snap, conf)
114
116
  if (!v.children.ulength) break
115
117
 
116
118
  stack.push(ptr)
@@ -126,7 +128,7 @@ module.exports = class WriteBatch {
126
128
  c = b4a.compare(target, m.key)
127
129
 
128
130
  if (c === 0) {
129
- const existing = await snap.inflateValue(m)
131
+ const existing = await snap.inflateValue(m, conf)
130
132
  if (b4a.equals(existing, value)) return false
131
133
  v.setValue(this.tree.context, mid, value)
132
134
  for (let i = 0; i < stack.length; i++) stack[i].changed = true
@@ -141,13 +143,13 @@ module.exports = class WriteBatch {
141
143
  ptr = v.children.uget(i)
142
144
  }
143
145
 
144
- const v = await retainAndInflate(ptr, snap)
146
+ const v = await retainAndInflate(ptr, snap, conf)
145
147
  let status = v.insertLeaf(this.tree.context, target, value)
146
148
 
147
149
  if (status >= 0) {
148
150
  // already exists, upsert if changed
149
151
  const m = v.keys.uget(status)
150
- const existing = await snap.inflateValue(m)
152
+ const existing = await snap.inflateValue(m, conf)
151
153
  if (b4a.equals(existing, value)) return false
152
154
  v.setValue(this.tree.context, status, value)
153
155
  }
@@ -156,12 +158,12 @@ module.exports = class WriteBatch {
156
158
  for (let i = 0; i < stack.length; i++) stack[i].changed = true
157
159
 
158
160
  while (status === NEEDS_SPLIT) {
159
- const v = await retainAndInflate(ptr, snap)
161
+ const v = await retainAndInflate(ptr, snap, conf)
160
162
  const parent = stack.pop()
161
163
  const { median, right } = v.split(this.tree.context)
162
164
 
163
165
  if (parent) {
164
- const p = await retainAndInflate(parent, snap)
166
+ const p = await retainAndInflate(parent, snap, conf)
165
167
  status = p.insertNode(this.tree.context, median, right)
166
168
  ptr = parent
167
169
  } else {
@@ -182,7 +184,7 @@ module.exports = class WriteBatch {
182
184
  const stack = []
183
185
 
184
186
  while (true) {
185
- const v = await retainAndInflate(ptr, this.snapshot)
187
+ const v = await retainAndInflate(ptr, this.snapshot, this.config)
186
188
  stack.push(ptr)
187
189
 
188
190
  let s = 0
@@ -217,6 +219,7 @@ module.exports = class WriteBatch {
217
219
 
218
220
  async _setKeyToNearestLeaf(v, index, stack) {
219
221
  const snap = this.snapshot
222
+ const conf = this.config
220
223
 
221
224
  let left = v.children.uget(index)
222
225
  let right = v.children.uget(index + 1)
@@ -226,21 +229,21 @@ module.exports = class WriteBatch {
226
229
  if (ls < rs) {
227
230
  // if fewer leaves on the left
228
231
  stack.push(right)
229
- let r = await retainAndInflate(right, snap)
232
+ let r = await retainAndInflate(right, snap, conf)
230
233
  while (r.children.ulength) {
231
234
  right = r.children.uget(0)
232
235
  stack.push(right)
233
- r = await retainAndInflate(right, snap)
236
+ r = await retainAndInflate(right, snap, conf)
234
237
  }
235
238
  v.keys.set(index, r.keys.shift())
236
239
  } else {
237
240
  // if fewer leaves on the right
238
241
  stack.push(left)
239
- let l = await retainAndInflate(left, snap)
242
+ let l = await retainAndInflate(left, snap, conf)
240
243
  while (l.children.ulength) {
241
244
  left = l.children.uget(l.children.ulength - 1)
242
245
  stack.push(left)
243
- l = await retainAndInflate(left, snap)
246
+ l = await retainAndInflate(left, snap, conf)
244
247
  }
245
248
  v.keys.set(index, l.keys.pop())
246
249
  }
@@ -248,11 +251,12 @@ module.exports = class WriteBatch {
248
251
 
249
252
  async _leafSize(ptr, goLeft) {
250
253
  const snap = this.snapshot
254
+ const conf = this.config
251
255
 
252
- let v = await retainAndInflate(ptr, snap)
256
+ let v = await retainAndInflate(ptr, snap, conf)
253
257
  while (v.children.ulength) {
254
258
  ptr = v.children.uget(goLeft ? 0 : v.children.ulength - 1)
255
- v = await retainAndInflate(ptr, snap)
259
+ v = await retainAndInflate(ptr, snap, conf)
256
260
  }
257
261
  return v.keys.ulength
258
262
  }
@@ -261,20 +265,21 @@ module.exports = class WriteBatch {
261
265
  const root = stack[0]
262
266
  const minKeys = this.tree.context.minKeys
263
267
  const snap = this.snapshot
268
+ const conf = this.config
264
269
 
265
270
  while (stack.length > 1) {
266
271
  const ptr = stack.pop()
267
272
  const parent = stack[stack.length - 1]
268
273
 
269
- const v = await retainAndInflate(ptr, snap)
274
+ const v = await retainAndInflate(ptr, snap, conf)
270
275
 
271
276
  if (v.keys.ulength >= minKeys) return root
272
277
 
273
- const p = await retainAndInflate(parent, snap)
278
+ const p = await retainAndInflate(parent, snap, conf)
274
279
 
275
280
  let { left, index, right } = v.siblings(p)
276
281
 
277
- let l = left && (await retainAndInflate(left, snap))
282
+ let l = left && (await retainAndInflate(left, snap, conf))
278
283
 
279
284
  // maybe borrow from left sibling?
280
285
  if (l && l.keys.ulength > minKeys) {
@@ -285,7 +290,7 @@ module.exports = class WriteBatch {
285
290
  return root
286
291
  }
287
292
 
288
- let r = right && (await retainAndInflate(right, snap))
293
+ let r = right && (await retainAndInflate(right, snap, conf))
289
294
 
290
295
  // maybe borrow from right sibling?
291
296
  if (r && r.keys.ulength > minKeys) {
@@ -313,7 +318,7 @@ module.exports = class WriteBatch {
313
318
  p.removeKey(index)
314
319
  }
315
320
 
316
- const r = await retainAndInflate(root, snap)
321
+ const r = await retainAndInflate(root, snap, conf)
317
322
  // check if the tree shrunk
318
323
  if (!r.keys.ulength && r.children.ulength) return r.children.uget(0)
319
324
  return root
@@ -330,7 +335,7 @@ module.exports = class WriteBatch {
330
335
  return
331
336
  }
332
337
 
333
- if (!this.root.value) await this.snapshot.inflate(this.root)
338
+ if (!this.root.value) await this.snapshot.inflate(this.root, this.config)
334
339
 
335
340
  let update = { size: 0, nodes: [], keys: [], values: [] }
336
341
  let minValue = -1
@@ -342,9 +347,9 @@ module.exports = class WriteBatch {
342
347
  const values = []
343
348
 
344
349
  const context = this.tree.context.getLocalContext()
345
- const activeRequests = this.tree.activeRequests
350
+ const config = this.tree.config
346
351
 
347
- await context.update(activeRequests)
352
+ await context.update(config)
348
353
 
349
354
  while (stack.length > 0) {
350
355
  const node = stack.pop()
@@ -485,7 +490,7 @@ module.exports = class WriteBatch {
485
490
  const buffers = new Array(blocks.length)
486
491
 
487
492
  if (blocks.length > 0 && this.length > 0) {
488
- const core = this.key ? await context.getCoreOffsetByKey(this.key, activeRequests) : 0
493
+ const core = this.key ? await context.getCoreOffsetByKey(this.key, config) : 0
489
494
  blocks[blocks.length - 1].previous = { core, seq: this.length - 1 }
490
495
  }
491
496
 
@@ -600,11 +605,11 @@ function supportsCompression(type) {
600
605
  return type !== TYPE_COMPAT && type !== 0
601
606
  }
602
607
 
603
- async function retainAndInflate(ptr, snap) {
608
+ async function retainAndInflate(ptr, snap, conf) {
604
609
  if (ptr.value) {
605
610
  ptr.retain()
606
611
  return ptr.value
607
612
  }
608
613
  ptr.retain()
609
- return await snap.inflate(ptr)
614
+ return await snap.inflate(ptr, conf)
610
615
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperbee2",
3
- "version": "2.3.0",
3
+ "version": "2.4.2",
4
4
  "description": "btree",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -19,6 +19,7 @@
19
19
  "b4a": "^1.6.7",
20
20
  "compact-encoding": "^2.16.1",
21
21
  "hypercore": "^11.15.0",
22
+ "hypercore-errors": "^1.5.0",
22
23
  "hyperschema": "^1.14.0",
23
24
  "protocol-buffers-encodings": "^1.2.0",
24
25
  "scope-lock": "^1.2.4",