fix: livechat transcript uploaded truncated to one of its rooms
Proposed changes (including videos or screenshots)
Split out of #35305 (NatsBroker). The bug doesn't depend on NATS.
When a livechat transcript is generated, OmnichannelTranscript.uploadFiles uploads the rendered PDF to two rooms and hands the same Readable to both Upload.uploadFileFromStream calls. A stream is consumed once. Two consumers that attach in the same tick both get every chunk, but a consumer that attaches one I/O turn later only gets what is left, which can be nothing:
second consumer attaches first gets second gets
same tick 51200 51200
after 1 microtask 51200 51200
after setImmediate 51200 0
omnichannel-transcript runs as its own service and Upload lives in the monolith, so each upload is a remote call. Nothing guarantees both start reading in the same tick.
The fix pipes the render into one PassThrough per upload, attached before anything awaits, so every upload reads its own full copy. The PDF is still streamed, not buffered. A render failure is forwarded to every copy, so the uploads fail instead of hanging.
Issue(s)
Split from #35305.
Steps to test or reproduce
yarn workspace @rocket.chat/omnichannel-services test. Two new specs in OmnichannelTranscript.spec.ts:
- the whole transcript reaches every room, even when one upload starts reading late. This fails against the current code: the second room gets 0 bytes.
- a failed render fails every upload. This fails (hangs) if the error forwarding is removed.
Further comments
I haven't reproduced this against a running microservices stack. The spec simulates the late reader.
๐ค Generated with Claude Code
Summary by CodeRabbit
- Bug Fixes
- Fixed an issue where livechat transcript PDFs sent to multiple rooms could arrive empty or truncated. Uploads now receive the complete transcript, and failures during PDF rendering are reported instead of leaving uploads waiting.