File size: 2,363 Bytes
fc93158 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | export type DraftStreamLoop = {
update: (text: string) => void;
flush: () => Promise<void>;
stop: () => void;
resetPending: () => void;
resetThrottleWindow: () => void;
waitForInFlight: () => Promise<void>;
};
export function createDraftStreamLoop(params: {
throttleMs: number;
isStopped: () => boolean;
sendOrEditStreamMessage: (text: string) => Promise<void | boolean>;
}): DraftStreamLoop {
let lastSentAt = 0;
let pendingText = "";
let inFlightPromise: Promise<void | boolean> | undefined;
let timer: ReturnType<typeof setTimeout> | undefined;
const flush = async () => {
if (timer) {
clearTimeout(timer);
timer = undefined;
}
while (!params.isStopped()) {
if (inFlightPromise) {
await inFlightPromise;
continue;
}
const text = pendingText;
if (!text.trim()) {
pendingText = "";
return;
}
pendingText = "";
const current = params.sendOrEditStreamMessage(text).finally(() => {
if (inFlightPromise === current) {
inFlightPromise = undefined;
}
});
inFlightPromise = current;
const sent = await current;
if (sent === false) {
pendingText = text;
return;
}
lastSentAt = Date.now();
if (!pendingText) {
return;
}
}
};
const schedule = () => {
if (timer) {
return;
}
const delay = Math.max(0, params.throttleMs - (Date.now() - lastSentAt));
timer = setTimeout(() => {
void flush();
}, delay);
};
return {
update: (text: string) => {
if (params.isStopped()) {
return;
}
pendingText = text;
if (inFlightPromise) {
schedule();
return;
}
if (!timer && Date.now() - lastSentAt >= params.throttleMs) {
void flush();
return;
}
schedule();
},
flush,
stop: () => {
pendingText = "";
if (timer) {
clearTimeout(timer);
timer = undefined;
}
},
resetPending: () => {
pendingText = "";
},
resetThrottleWindow: () => {
lastSentAt = 0;
if (timer) {
clearTimeout(timer);
timer = undefined;
}
},
waitForInFlight: async () => {
if (inFlightPromise) {
await inFlightPromise;
}
},
};
}
|