streams icon indicating copy to clipboard operation
streams copied to clipboard

How to create a transformed WritableStream that waits for close?

Open yume-chan opened this issue 2 years ago • 0 comments

Now I have this API:

export function adbSyncPush(
    stream: AdbBufferedStream,
    writer: WritableStreamDefaultWriter<Uint8Array>,
    filename: string,
    mode: number = (LinuxFileType.File << 12) | 0o666,
    mtime: number = (Date.now() / 1000) | 0,
    packetSize: number = ADB_SYNC_MAX_PACKET_SIZE,
): WritableStream<Uint8Array> {
    // FIXME: `ChunkStream` can't forward `close` Promise.
    const { readable, writable } = new ChunkStream(packetSize);
    readable.pipeTo(new WritableStream<Uint8Array>({
        async start() {
            const pathAndMode = `${filename},${mode.toString()}`;
            await adbSyncWriteRequest(writer, AdbSyncRequestId.Send, pathAndMode);
        },
        async write(chunk) {
            await adbSyncWriteRequest(writer, AdbSyncRequestId.Data, chunk);
        },
        async close() {
            await adbSyncWriteRequest(writer, AdbSyncRequestId.Done, mtime);
            await adbSyncReadResponse(stream, ResponseTypes);
        }
    }, {
        highWaterMark: 16 * 1024,
        size(chunk) { return chunk.byteLength; }
    }));
    return writable;
}

It returns a WrtiableStream to let the caller write a file on device, the close handler tells the device to finish the file and return the final result. Let's call it PushFileStream.

Because each packet can't exceed packetSize length, I need to split each incoming chunks. I think I can re-use the ChunkStream (a TransformStream) that's used somewhere else, so I piped the readable end to PushFileStream, and returned the writable end of the ChunkStream to callers.

It can correctly chunk the incoming data and send them to device, however, the writable of ChunkStream won't wait for close of PushFileStream. If the caller want to close the stream and writer after finishing pushing, they may be closed before close, causing push to fail.

So how can I wait for PushFileStream close, or how can I generally use TransformStream when creating a WritableStream?

yume-chan avatar Feb 24 '22 02:02 yume-chan