perf(jsonl): add reusable zstd frame decoders

This commit is contained in:
imccyu
2026-08-05 17:27:02 +08:00
parent 906ab15490
commit 353226246e
3 changed files with 230 additions and 1 deletions

View File

@@ -5,8 +5,12 @@
* @module dsh-session-persistence-jsonl/zstd
*/
import { constants, zstdCompress, zstdDecompress, type ZstdOptions } from 'node:zlib'
import {
constants, zstdCompress, zstdDecompress, zstdDecompressSync, type ZstdOptions,
} from 'node:zlib'
import { promisify } from 'node:util'
import { NodePrivateZstdFrameDecoder } from './zstd-private-decoder.ts'
import { PublicZstdFrameDecoder } from './zstd-public-decoder.ts'
const ZSTD_MAGIC = 0xFD2FB528
const zstdCompressAsync = promisify(zstdCompress)
@@ -117,6 +121,40 @@ export async function decompressZstdFrame(input: Buffer): Promise<Buffer> {
return zstdDecompressAsync(input)
}
/**
* Synchronously decompress one complete frame and validate its checksum.
* Complete-log readers time-slice repeated calls so the event loop regains
* control without paying one asynchronous native dispatch per frame.
* @param input - one structurally complete Zstandard frame.
* @returns the frame plaintext.
*/
export function decompressZstdFrameSync(input: Buffer): Buffer {
return zstdDecompressSync(input)
}
/** Common lifecycle for interchangeable synchronous multi-frame decoders. */
export interface ZstdFrameDecoder {
/**
* Decode and checksum complete frames in source order. Each yielded buffer
* remains valid only until the iterator advances to the next frame.
* @param source - concatenated Zstandard frame bytes.
* @param frames - structurally complete ranges within `source`.
* @returns one plaintext buffer per frame.
*/
decode(source: Buffer, frames: readonly ZstdFrameRange[]): Generator<Buffer, void, void>
/** Release decoder-owned resources; repeated calls are harmless. */
close(): void
}
/**
* Select the shared private decoder when the running Node 22/24/26 shape is
* compatible, otherwise preserve correctness with the public one-shot API.
* @returns a synchronous decoder with an implementation-independent lifecycle.
*/
export function createZstdFrameDecoder(): ZstdFrameDecoder {
return NodePrivateZstdFrameDecoder.create() ?? new PublicZstdFrameDecoder()
}
/**
* Recover available plaintext from a structurally incomplete final frame.
* `ZSTD_e_flush` deliberately suppresses final-frame and checksum completion;