Queue Release Build / prepare (push) Successful in 20s
Deploy Web Apps / deploy (push) Successful in 9m2s
Queue Release Build / build-windows (push) Successful in 28m8s
Queue Release Build / build-linux (push) Successful in 47m26s
Queue Release Build / build-android (push) Successful in 19m52s
Queue Release Build / finalize (push) Successful in 4m42s
Stream large receives to disk with chunk acks to cap renderer RAM, evict off-screen display blobs, and route exports through a disk-aware download service. Fix the high-memory dialog (backdrop dismiss, copy, log actions), allow diagnostics paths in the path jail, and restore persisted image hydration after reload. Co-authored-by: Cursor <cursoragent@cursor.com>
48 lines
1.2 KiB
TypeScript
48 lines
1.2 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
|
|
import { buildAttachmentChunkAckKey } from '../../domain/logic/attachment-chunk-ack.rules';
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class AttachmentChunkAckService {
|
|
private readonly waiters = new Map<string, () => void>();
|
|
|
|
waitForAck(
|
|
messageId: string,
|
|
fileId: string,
|
|
index: number,
|
|
timeoutMs = 60_000
|
|
): Promise<void> {
|
|
const key = buildAttachmentChunkAckKey(messageId, fileId, index);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const timer = setTimeout(() => {
|
|
this.waiters.delete(key);
|
|
reject(new Error('attachment chunk ack timeout'));
|
|
}, timeoutMs);
|
|
|
|
this.waiters.set(key, () => {
|
|
clearTimeout(timer);
|
|
this.waiters.delete(key);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
resolveAck(messageId: string, fileId: string, index: number): void {
|
|
this.waiters.get(buildAttachmentChunkAckKey(messageId, fileId, index))?.();
|
|
}
|
|
|
|
cancelPendingForFile(messageId: string, fileId: string): void {
|
|
const prefix = `${messageId}:${fileId}:`;
|
|
|
|
for (const [key, resolve] of this.waiters) {
|
|
if (!key.startsWith(prefix)) {
|
|
continue;
|
|
}
|
|
|
|
resolve();
|
|
this.waiters.delete(key);
|
|
}
|
|
}
|
|
}
|