mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 15:30:39 +00:00
refactor(queue): share drain helpers across announce and reply
This commit is contained in:
@@ -8,9 +8,10 @@ import {
|
||||
import {
|
||||
applyQueueRuntimeSettings,
|
||||
applyQueueDropPolicy,
|
||||
beginQueueDrain,
|
||||
buildCollectPrompt,
|
||||
clearQueueSummaryState,
|
||||
drainCollectItemIfNeeded,
|
||||
drainCollectQueueStep,
|
||||
drainNextQueueItem,
|
||||
hasCrossChannelItems,
|
||||
previewQueueSummaryPrompt,
|
||||
@@ -97,33 +98,35 @@ function getAnnounceQueue(
|
||||
return created;
|
||||
}
|
||||
|
||||
function hasAnnounceCrossChannelItems(items: AnnounceQueueItem[]): boolean {
|
||||
return hasCrossChannelItems(items, (item) => {
|
||||
if (!item.origin) {
|
||||
return {};
|
||||
}
|
||||
if (!item.originKey) {
|
||||
return { cross: true };
|
||||
}
|
||||
return { key: item.originKey };
|
||||
});
|
||||
}
|
||||
|
||||
function scheduleAnnounceDrain(key: string) {
|
||||
const queue = ANNOUNCE_QUEUES.get(key);
|
||||
if (!queue || queue.draining) {
|
||||
const queue = beginQueueDrain(ANNOUNCE_QUEUES, key);
|
||||
if (!queue) {
|
||||
return;
|
||||
}
|
||||
queue.draining = true;
|
||||
void (async () => {
|
||||
try {
|
||||
let forceIndividualCollect = false;
|
||||
while (queue.items.length > 0 || queue.droppedCount > 0) {
|
||||
const collectState = { forceIndividualCollect: false };
|
||||
for (;;) {
|
||||
if (queue.items.length === 0 && queue.droppedCount === 0) {
|
||||
break;
|
||||
}
|
||||
await waitForQueueDebounce(queue);
|
||||
if (queue.mode === "collect") {
|
||||
const isCrossChannel = hasCrossChannelItems(queue.items, (item) => {
|
||||
if (!item.origin) {
|
||||
return {};
|
||||
}
|
||||
if (!item.originKey) {
|
||||
return { cross: true };
|
||||
}
|
||||
return { key: item.originKey };
|
||||
});
|
||||
const collectDrainResult = await drainCollectItemIfNeeded({
|
||||
forceIndividualCollect,
|
||||
isCrossChannel,
|
||||
setForceIndividualCollect: (next) => {
|
||||
forceIndividualCollect = next;
|
||||
},
|
||||
const collectDrainResult = await drainCollectQueueStep({
|
||||
collectState,
|
||||
isCrossChannel: hasAnnounceCrossChannelItems(queue.items),
|
||||
items: queue.items,
|
||||
run: async (item) => await queue.send(item),
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { defaultRuntime } from "../../../runtime.js";
|
||||
import {
|
||||
buildCollectPrompt,
|
||||
beginQueueDrain,
|
||||
clearQueueSummaryState,
|
||||
drainCollectItemIfNeeded,
|
||||
drainCollectQueueStep,
|
||||
drainNextQueueItem,
|
||||
hasCrossChannelItems,
|
||||
previewQueueSummaryPrompt,
|
||||
@@ -16,14 +17,13 @@ export function scheduleFollowupDrain(
|
||||
key: string,
|
||||
runFollowup: (run: FollowupRun) => Promise<void>,
|
||||
): void {
|
||||
const queue = FOLLOWUP_QUEUES.get(key);
|
||||
if (!queue || queue.draining) {
|
||||
const queue = beginQueueDrain(FOLLOWUP_QUEUES, key);
|
||||
if (!queue) {
|
||||
return;
|
||||
}
|
||||
queue.draining = true;
|
||||
void (async () => {
|
||||
try {
|
||||
let forceIndividualCollect = false;
|
||||
const collectState = { forceIndividualCollect: false };
|
||||
while (queue.items.length > 0 || queue.droppedCount > 0) {
|
||||
await waitForQueueDebounce(queue);
|
||||
if (queue.mode === "collect") {
|
||||
@@ -50,12 +50,9 @@ export function scheduleFollowupDrain(
|
||||
};
|
||||
});
|
||||
|
||||
const collectDrainResult = await drainCollectItemIfNeeded({
|
||||
forceIndividualCollect,
|
||||
const collectDrainResult = await drainCollectQueueStep({
|
||||
collectState,
|
||||
isCrossChannel,
|
||||
setForceIndividualCollect: (next) => {
|
||||
forceIndividualCollect = next;
|
||||
},
|
||||
items: queue.items,
|
||||
run: runFollowup,
|
||||
});
|
||||
|
||||
@@ -132,6 +132,18 @@ export function waitForQueueDebounce(queue: {
|
||||
});
|
||||
}
|
||||
|
||||
export function beginQueueDrain<T extends { draining: boolean }>(
|
||||
map: Map<string, T>,
|
||||
key: string,
|
||||
): T | undefined {
|
||||
const queue = map.get(key);
|
||||
if (!queue || queue.draining) {
|
||||
return undefined;
|
||||
}
|
||||
queue.draining = true;
|
||||
return queue;
|
||||
}
|
||||
|
||||
export async function drainNextQueueItem<T>(
|
||||
items: T[],
|
||||
run: (item: T) => Promise<void>,
|
||||
@@ -162,6 +174,23 @@ export async function drainCollectItemIfNeeded<T>(params: {
|
||||
return drained ? "drained" : "empty";
|
||||
}
|
||||
|
||||
export async function drainCollectQueueStep<T>(params: {
|
||||
collectState: { forceIndividualCollect: boolean };
|
||||
isCrossChannel: boolean;
|
||||
items: T[];
|
||||
run: (item: T) => Promise<void>;
|
||||
}): Promise<"skipped" | "drained" | "empty"> {
|
||||
return await drainCollectItemIfNeeded({
|
||||
forceIndividualCollect: params.collectState.forceIndividualCollect,
|
||||
isCrossChannel: params.isCrossChannel,
|
||||
setForceIndividualCollect: (next) => {
|
||||
params.collectState.forceIndividualCollect = next;
|
||||
},
|
||||
items: params.items,
|
||||
run: params.run,
|
||||
});
|
||||
}
|
||||
|
||||
export function buildQueueSummaryPrompt(params: {
|
||||
state: QueueSummaryState;
|
||||
noun: string;
|
||||
|
||||
Reference in New Issue
Block a user