From d9eee572dfdfb7dac0d37031579da903ee5e8481 Mon Sep 17 00:00:00 2001 From: Caolan McMahon Date: Tue, 24 Mar 2026 17:02:53 +0000 Subject: [PATCH 1/3] Temporary workaround: register of in-progress getBlock requests --- lib/context.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/context.js b/lib/context.js index eeeb840..9e33e80 100644 --- a/lib/context.js +++ b/lib/context.js @@ -30,6 +30,7 @@ class CoreContext { this.opened = [] this.cores = [] this.changed = false + this.inProgress = new Map() } // TODO: remove, left here for easier debugging for now @@ -155,17 +156,28 @@ class CoreContext { return this.cores[index - 1].key } - async getBlock(seq, core, config) { - if (core !== 0 && core - 1 >= this.cores.length) await this.update(config) + getBlock(seq, core, config) { + if (!this.inProgress.has(core)) { + this.inProgress.set(core, new Map()) + } + if (this.inProgress.get(core).has(seq)) { + return this.inProgress.get(core).get(seq) + } + const promise = (async () => { + if (core !== 0 && core - 1 >= this.cores.length) await this.update(config) - const hc = this.getCore(core) - const buffer = await hc.get(seq, config) - if (buffer === null) throw BLOCK_NOT_AVAILABLE() + const hc = this.getCore(core) + const buffer = await hc.get(seq, config) + if (buffer === null) throw BLOCK_NOT_AVAILABLE() - if (config.trace !== null) config.trace(core, seq) + if (config.trace !== null) config.trace(core, seq) - const block = decodeBlock(buffer, seq) - return block + const block = decodeBlock(buffer, seq) + this.inProgress.get(core).delete(seq) + return block + })() + this.inProgress.get(core).set(seq, promise) + return promise } getLocalContext() { From 1de7d91bbd49d9bbf5d9c25e18a9f7e13cf3ce71 Mon Sep 17 00:00:00 2001 From: Caolan McMahon Date: Tue, 7 Apr 2026 14:21:51 +0100 Subject: [PATCH 2/3] Revert "Temporary workaround: register of in-progress getBlock requests" This reverts commit cfd4d80e0df122da918d0d7d9a4a0f16de605a66. --- lib/context.js | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/lib/context.js b/lib/context.js index 9e33e80..eeeb840 100644 --- a/lib/context.js +++ b/lib/context.js @@ -30,7 +30,6 @@ class CoreContext { this.opened = [] this.cores = [] this.changed = false - this.inProgress = new Map() } // TODO: remove, left here for easier debugging for now @@ -156,28 +155,17 @@ class CoreContext { return this.cores[index - 1].key } - getBlock(seq, core, config) { - if (!this.inProgress.has(core)) { - this.inProgress.set(core, new Map()) - } - if (this.inProgress.get(core).has(seq)) { - return this.inProgress.get(core).get(seq) - } - const promise = (async () => { - if (core !== 0 && core - 1 >= this.cores.length) await this.update(config) + async getBlock(seq, core, config) { + if (core !== 0 && core - 1 >= this.cores.length) await this.update(config) - const hc = this.getCore(core) - const buffer = await hc.get(seq, config) - if (buffer === null) throw BLOCK_NOT_AVAILABLE() + const hc = this.getCore(core) + const buffer = await hc.get(seq, config) + if (buffer === null) throw BLOCK_NOT_AVAILABLE() - if (config.trace !== null) config.trace(core, seq) + if (config.trace !== null) config.trace(core, seq) - const block = decodeBlock(buffer, seq) - this.inProgress.get(core).delete(seq) - return block - })() - this.inProgress.get(core).set(seq, promise) - return promise + const block = decodeBlock(buffer, seq) + return block } getLocalContext() { From 2d1b4fd570394e837ec70bd792029bebc827223e Mon Sep 17 00:00:00 2001 From: Caolan McMahon Date: Tue, 7 Apr 2026 13:50:25 +0100 Subject: [PATCH 3/3] Use pending inflate task when available --- lib/inflate.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/inflate.js b/lib/inflate.js index b1bf1ce..42b812e 100644 --- a/lib/inflate.js +++ b/lib/inflate.js @@ -2,9 +2,21 @@ const b4a = require('b4a') const { Pointer, KeyPointer, ValuePointer, TreeNode } = require('./tree.js') const { DeltaOp, DeltaCohort, OP_COHORT } = require('./compression.js') +const pending = new WeakMap() + exports.inflate = async function inflate(ptr, config) { if (ptr.value) return ptr.value + if (pending.has(ptr)) return pending.get(ptr) + const promise = _inflate(ptr, config) + pending.set(ptr, promise) + try { + return await promise + } finally { + pending.delete(ptr) + } +} +async function _inflate(ptr, config) { const [block, context] = await Promise.all([ ptr.context.getBlock(ptr.seq, ptr.core, config), ptr.context.getContext(ptr.core, config)