feat(messaging-streams): manually deepen all six stream utility modules
- chunker: framed seq chunks, reassemble, setChunkSize - multiplex: closeAll, getStream, per-stream byte counters - backpressure: low/high water marks, bufferedBytes - tee: branchBytes, removeBranch, depth guard - transform: pipeTo and outbound backpressure - resume-token: labeled checkpoints, clearTokens, bytesFromOffset - Update category README and chunker tests Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -9,7 +9,9 @@ class HyperP2PStreamChunker extends EventEmitter {
|
||||
super()
|
||||
this.chunkSize = opts.chunkSize || 4096
|
||||
this._pending = b4a.alloc(0)
|
||||
this._stats = { chunks: 0, bytes: 0 }
|
||||
this._seq = 0
|
||||
this._parts = []
|
||||
this._stats = { chunks: 0, bytes: 0, flushed: 0 }
|
||||
}
|
||||
|
||||
push (data) {
|
||||
@@ -20,17 +22,28 @@ class HyperP2PStreamChunker extends EventEmitter {
|
||||
while (this._pending.length >= this.chunkSize) {
|
||||
const slice = this._pending.subarray(0, this.chunkSize)
|
||||
this._pending = this._pending.subarray(this.chunkSize)
|
||||
this._stats.chunks++
|
||||
emitted.push(slice)
|
||||
this.emit('chunk', slice)
|
||||
const framed = this._frame(slice)
|
||||
emitted.push(framed)
|
||||
this._parts.push(framed.data)
|
||||
this.emit('chunk', framed)
|
||||
}
|
||||
return emitted
|
||||
}
|
||||
|
||||
pendingLength () { return this._pending.length }
|
||||
_frame (data) {
|
||||
const seq = this._seq++
|
||||
this._stats.chunks++
|
||||
return { seq, data, size: data.length }
|
||||
}
|
||||
|
||||
pendingLength () {
|
||||
return this._pending.length
|
||||
}
|
||||
|
||||
reset () {
|
||||
this._pending = b4a.alloc(0)
|
||||
this._seq = 0
|
||||
this._parts = []
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -38,17 +51,52 @@ class HyperP2PStreamChunker extends EventEmitter {
|
||||
if (!this._pending.length) return null
|
||||
const tail = this._pending
|
||||
this._pending = b4a.alloc(0)
|
||||
this._stats.chunks++
|
||||
this.emit('chunk', tail)
|
||||
return tail
|
||||
const framed = this._frame(tail)
|
||||
this._parts.push(framed.data)
|
||||
this._stats.flushed++
|
||||
this.emit('chunk', framed)
|
||||
return framed
|
||||
}
|
||||
|
||||
reassemble () {
|
||||
if (!this._parts.length) return b4a.alloc(0)
|
||||
return b4a.concat(this._parts)
|
||||
}
|
||||
|
||||
reassembleFrom (chunks) {
|
||||
if (!Array.isArray(chunks)) throw new Error('chunks must be an array')
|
||||
const bufs = chunks.map((c) => (c && c.data ? c.data : c))
|
||||
return b4a.concat(bufs)
|
||||
}
|
||||
|
||||
setChunkSize (n) {
|
||||
const size = Number(n)
|
||||
if (!Number.isFinite(size) || size < 1) throw new Error('chunkSize must be positive')
|
||||
this.chunkSize = size
|
||||
return this.chunkSize
|
||||
}
|
||||
|
||||
chunkCount () {
|
||||
return this._stats.chunks
|
||||
}
|
||||
|
||||
getStats () {
|
||||
return { ...this._stats, pending: this._pending.length, protocol: PROTOCOL }
|
||||
return {
|
||||
...this._stats,
|
||||
pending: this._pending.length,
|
||||
chunkSize: this.chunkSize,
|
||||
protocol: PROTOCOL
|
||||
}
|
||||
}
|
||||
|
||||
async ready () { return this }
|
||||
async close () { this._pending = b4a.alloc(0) }
|
||||
async ready () {
|
||||
return this
|
||||
}
|
||||
|
||||
async close () {
|
||||
this.reset()
|
||||
this.emit('closed')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { HyperP2PStreamChunker, PROTOCOL }
|
||||
|
||||
@@ -8,7 +8,16 @@ test('split chunks', async (t) => {
|
||||
const m = new HyperP2PStreamChunker({ chunkSize: 4 })
|
||||
const parts = m.push(require('b4a').from('abcdefgh'))
|
||||
t.is(parts.length, 2)
|
||||
t.is(parts[0].length, 4)
|
||||
t.is(parts[0].data.length, 4)
|
||||
t.is(parts[0].seq, 0)
|
||||
await m.close()
|
||||
})
|
||||
|
||||
test('reassemble', async (t) => {
|
||||
const m = new HyperP2PStreamChunker({ chunkSize: 3 })
|
||||
m.push(require('b4a').from('hello'))
|
||||
m.flush()
|
||||
t.is(m.reassemble().toString(), 'hello')
|
||||
await m.close()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user