diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/transport.js | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js index 844a201..df2abb0 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js @@ -562,6 +562,18 @@ class MeshBayTransport { } /** + * Nobody is watching any more. + * + * Closing the viewer used to say nothing to the node, which went on + * transcoding and holding one of its two slots until the credit timeout — so + * the next video answered "server busy". + */ + stopStream() { + if (!this._connected) return; + try { this._send({ type: 'stream_stop', v: '0.1' }); } catch { /* gone */ } + } + + /** * Push a whole file, several chunks in flight at once. * * One chunk per round trip is 48 KB of throughput per RTT no matter how much @@ -778,6 +790,11 @@ class MeshBayTransport { }, 30000); this._pending.set(id, { _reqType: obj.type, + // Chunks are the one request that runs several at a time and can be + // interleaved with anything else on the channel. Matching them by + // arrival order was only ever true by luck; this makes it true. + _key: obj.type === 'file_req' + ? `chunk:${obj.file_id}:${obj.chunk_index}` : null, resolve: (msg) => { clearTimeout(timeout); this._pending.delete(id); resolve(msg); }, reject: (err) => { clearTimeout(timeout); this._pending.delete(id); reject(err); }, }); @@ -857,6 +874,24 @@ class MeshBayTransport { return; } + if (msg.type === 'file_chunk') { + const key = `chunk:${msg.file_id}:${msg.chunk_index}`; + for (const [, handler] of this._pending) { + // A node from before the reply carried a file_id: fall back to the + // index, which is still better than the oldest pending request. + const match = msg.file_id + ? handler._key === key + : handler._key && handler._key.endsWith(`:${msg.chunk_index}`); + if (match) { + handler.resolve(msg); + return; + } + } + // Nobody asked for it any more — a cancelled download, most likely. It + // must not be handed to whatever request happens to be waiting. + return; + } + const oldest = this._pending.entries().next(); if (!oldest.done) { const [, handler] = oldest.value; |