fix: Bug - Sending files between users doesn't really work (chunk-time size re-gate)
Remove the leftover MAX_AUTO_SAVE_SIZE_BYTES guard from handleFileChunk's in-memory path. The request gate (canReceiveAttachment) already admits 10-50 MB generic files for in-memory receive on stores without disk streaming (browser), but the chunk handler silently dropped every chunk of such files: no ack was sent, the sender's waitForAck timed out, and the receiver's GUI never changed. Receive admission is now decided once, at request time. Adds a two-browser regression e2e that sends an 11 MB generic file and asserts Request -> progress -> Download. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+30
@@ -629,6 +629,36 @@ describe('AttachmentTransferService', () => {
|
||||
expect(webrtc.sendToPeer).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('assembles generic files above the auto-save cap in memory when the store cannot stream but can persist them', async () => {
|
||||
// Browser receiver: no disk streaming, persistable up to 50 MB. The request
|
||||
// gate admits a 20 MB file for in-memory receive, so the chunk handler must
|
||||
// accept its chunks instead of dropping them with a file-too-large error.
|
||||
attachmentStorage.canStreamToDisk.mockReturnValue(false);
|
||||
attachmentStorage.canPersistSize.mockImplementation((bytes: number) => bytes <= 50 * 1024 * 1024);
|
||||
|
||||
const service = createService();
|
||||
const attachment = registerIncomingGenericFile(20 * 1024 * 1024);
|
||||
|
||||
service.handleFileChunk(chunkPayload(0, 2, [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]));
|
||||
|
||||
expect(attachment.requestError).toBeUndefined();
|
||||
expect(attachment.receivedBytes).toBe(3);
|
||||
|
||||
service.handleFileChunk(chunkPayload(1, 2, [
|
||||
4,
|
||||
5,
|
||||
6
|
||||
]));
|
||||
|
||||
await vi.waitFor(() => expect(attachment.available).toBe(true));
|
||||
|
||||
expect(attachment.objectUrl).toMatch(/^blob:/);
|
||||
});
|
||||
|
||||
it('assembles browser-sized generic files in memory when streaming is unavailable', async () => {
|
||||
attachmentStorage.canStreamToDisk.mockReturnValue(false);
|
||||
attachmentStorage.canPersistSize.mockImplementation((bytes: number) => bytes <= 50 * 1024 * 1024);
|
||||
|
||||
+5
-6
@@ -425,12 +425,11 @@ export class AttachmentTransferService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (attachment.size > MAX_AUTO_SAVE_SIZE_BYTES) {
|
||||
attachment.requestError = this.appI18n.instant(ATTACHMENT_FILE_TOO_LARGE_KEY);
|
||||
this.runtimeStore.touch();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reaching here means canReceiveAttachment passed and disk streaming is not
|
||||
// used, so the in-memory path is the agreed receive strategy - including
|
||||
// above-auto-save-cap files on stores that cannot stream but can persist
|
||||
// them (browser). A stricter size guard here would silently drop chunks the
|
||||
// request gate already admitted.
|
||||
const decodedBytes = this.transport.decodeBase64(data);
|
||||
const assemblyKey = `${messageId}:${fileId}`;
|
||||
const requestKey = this.buildRequestKey(messageId, fileId);
|
||||
|
||||
Reference in New Issue
Block a user