mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 12:11:23 +00:00
refactor(channels): share draft stream loop across slack and telegram
This commit is contained in:
92
src/channels/draft-stream-loop.ts
Normal file
92
src/channels/draft-stream-loop.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
export type DraftStreamLoop = {
|
||||
update: (text: string) => void;
|
||||
flush: () => Promise<void>;
|
||||
stop: () => void;
|
||||
resetPending: () => void;
|
||||
waitForInFlight: () => Promise<void>;
|
||||
};
|
||||
|
||||
export function createDraftStreamLoop(params: {
|
||||
throttleMs: number;
|
||||
isStopped: () => boolean;
|
||||
sendOrEditStreamMessage: (text: string) => Promise<void>;
|
||||
}): DraftStreamLoop {
|
||||
let lastSentAt = 0;
|
||||
let pendingText = "";
|
||||
let inFlightPromise: Promise<void> | 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 = "";
|
||||
lastSentAt = Date.now();
|
||||
const current = params.sendOrEditStreamMessage(text).finally(() => {
|
||||
if (inFlightPromise === current) {
|
||||
inFlightPromise = undefined;
|
||||
}
|
||||
});
|
||||
inFlightPromise = current;
|
||||
await current;
|
||||
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 = "";
|
||||
},
|
||||
waitForInFlight: async () => {
|
||||
if (inFlightPromise) {
|
||||
await inFlightPromise;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user