fix: livechat transcript uploaded truncated to one of its rooms

Merged
SA
9d ago
+79-6

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.