Commit 74264c5c by Archer Committed by GitHub

perf: stop loop (#6816)

* perf: stop loop

* fix: test
parent 306d797a
...@@ -32,6 +32,7 @@ export const dispatchLoop = async (props: Props): Promise<Response> => { ...@@ -32,6 +32,7 @@ export const dispatchLoop = async (props: Props): Promise<Response> => {
runtimeEdges, runtimeEdges,
lastInteractive, lastInteractive,
runtimeNodes, runtimeNodes,
checkIsStopping,
node: { name } node: { name }
} = props; } = props;
const { loopInputArray = [], childrenNodeIdList = [] } = params; const { loopInputArray = [], childrenNodeIdList = [] } = params;
...@@ -60,6 +61,9 @@ export const dispatchLoop = async (props: Props): Promise<Response> => { ...@@ -60,6 +61,9 @@ export const dispatchLoop = async (props: Props): Promise<Response> => {
let index = 0; let index = 0;
for await (const item of loopInputArray) { for await (const item of loopInputArray) {
if (checkIsStopping()) {
break;
}
// Skip already looped // Skip already looped
if (lastIndex && index < lastIndex) { if (lastIndex && index < lastIndex) {
index++; index++;
......
...@@ -41,7 +41,7 @@ type Props = ModuleDispatchProps<{ ...@@ -41,7 +41,7 @@ type Props = ModuleDispatchProps<{
type Response = DispatchNodeResultType<Record<string, any>>; type Response = DispatchNodeResultType<Record<string, any>>;
export const dispatchLoopRun = async (props: Props): Promise<Response> => { export const dispatchLoopRun = async (props: Props): Promise<Response> => {
const { params, runtimeNodes, runtimeEdges, node, lastInteractive } = props; const { params, runtimeNodes, runtimeEdges, node, lastInteractive, checkIsStopping } = props;
const { name } = node; const { name } = node;
const mode = params[NodeInputKeyEnum.loopRunMode] ?? LoopRunModeEnum.array; const mode = params[NodeInputKeyEnum.loopRunMode] ?? LoopRunModeEnum.array;
const childrenNodeIdList = params[NodeInputKeyEnum.childrenNodeIdList] ?? []; const childrenNodeIdList = params[NodeInputKeyEnum.childrenNodeIdList] ?? [];
...@@ -120,6 +120,9 @@ export const dispatchLoopRun = async (props: Props): Promise<Response> => { ...@@ -120,6 +120,9 @@ export const dispatchLoopRun = async (props: Props): Promise<Response> => {
let maxIterationsExceeded = false; let maxIterationsExceeded = false;
while (true) { while (true) {
if (checkIsStopping()) {
break;
}
// Check exhaustion before maxLength so `inputArray.length === maxLength` runs cleanly. // Check exhaustion before maxLength so `inputArray.length === maxLength` runs cleanly.
const arrayItem = (() => { const arrayItem = (() => {
if (mode !== LoopRunModeEnum.array) { if (mode !== LoopRunModeEnum.array) {
......
...@@ -35,7 +35,7 @@ type Response = DispatchNodeResultType<{ ...@@ -35,7 +35,7 @@ type Response = DispatchNodeResultType<{
}>; }>;
export const dispatchParallelRun = async (props: Props): Promise<Response> => { export const dispatchParallelRun = async (props: Props): Promise<Response> => {
const { params, runtimeNodes, runtimeEdges, node } = props; const { params, runtimeNodes, runtimeEdges, node, checkIsStopping } = props;
const { name } = node; const { name } = node;
const { const {
loopInputArray = [], loopInputArray = [],
...@@ -70,6 +70,9 @@ export const dispatchParallelRun = async (props: Props): Promise<Response> => { ...@@ -70,6 +70,9 @@ export const dispatchParallelRun = async (props: Props): Promise<Response> => {
let accumulatedPoints = 0; let accumulatedPoints = 0;
for (let attempt = 0; attempt < maxRetryAttempts + 1; attempt++) { for (let attempt = 0; attempt < maxRetryAttempts + 1; attempt++) {
if (checkIsStopping()) {
return;
}
const { taskRuntimeNodes, taskRuntimeEdges } = buildTaskRuntimeContext({ const { taskRuntimeNodes, taskRuntimeEdges } = buildTaskRuntimeContext({
runtimeNodes, runtimeNodes,
runtimeEdges, runtimeEdges,
...@@ -108,7 +111,7 @@ export const dispatchParallelRun = async (props: Props): Promise<Response> => { ...@@ -108,7 +111,7 @@ export const dispatchParallelRun = async (props: Props): Promise<Response> => {
// taskRuntimeNodes / taskRuntimeEdges go out of scope → GC // taskRuntimeNodes / taskRuntimeEdges go out of scope → GC
} }
return lastResult!; return lastResult;
}, },
concurrency concurrency
); );
...@@ -122,10 +125,13 @@ export const dispatchParallelRun = async (props: Props): Promise<Response> => { ...@@ -122,10 +125,13 @@ export const dispatchParallelRun = async (props: Props): Promise<Response> => {
responseDetails, responseDetails,
assistantResponses, assistantResponses,
customFeedbacks customFeedbacks
} = aggregateParallelResults(taskResults, { } = aggregateParallelResults(
taskInputs: loopInputArray, taskResults.filter((item) => item !== undefined),
parentNodeId: node.nodeId {
}); taskInputs: loopInputArray,
parentNodeId: node.nodeId
}
);
return { return {
data: { data: {
......
...@@ -171,7 +171,8 @@ const makeProps = ( ...@@ -171,7 +171,8 @@ const makeProps = (
runtimeEdges: [], runtimeEdges: [],
variables: {}, variables: {},
usagePush: vi.fn(), usagePush: vi.fn(),
lastInteractive: undefined lastInteractive: undefined,
checkIsStopping: () => false
} as any; } as any;
}; };
...@@ -216,7 +217,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => { ...@@ -216,7 +217,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => {
runtimeEdges: [], runtimeEdges: [],
variables: {}, variables: {},
usagePush: vi.fn(), usagePush: vi.fn(),
lastInteractive: undefined lastInteractive: undefined,
checkIsStopping: () => false
} as any; } as any;
const result: any = await dispatchLoopRun(props); const result: any = await dispatchLoopRun(props);
...@@ -268,7 +270,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => { ...@@ -268,7 +270,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => {
runtimeEdges: [], runtimeEdges: [],
variables: {}, variables: {},
usagePush: vi.fn(), usagePush: vi.fn(),
lastInteractive: undefined lastInteractive: undefined,
checkIsStopping: () => false
} as any; } as any;
const result: any = await dispatchLoopRun(props); const result: any = await dispatchLoopRun(props);
...@@ -482,7 +485,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => { ...@@ -482,7 +485,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => {
iteration: 2, iteration: 2,
childrenResponse: { entryNodeIds: ['userSelectNode'] } childrenResponse: { entryNodeIds: ['userSelectNode'] }
} }
} },
checkIsStopping: () => false
} as any; } as any;
const result: any = await dispatchLoopRun(props); const result: any = await dispatchLoopRun(props);
...@@ -533,7 +537,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => { ...@@ -533,7 +537,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => {
iteration: 2, iteration: 2,
childrenResponse: interactivePayload childrenResponse: interactivePayload
} }
} },
checkIsStopping: () => false
} as any; } as any;
await dispatchLoopRun(props); await dispatchLoopRun(props);
...@@ -611,7 +616,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => { ...@@ -611,7 +616,8 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => {
runtimeEdges: [], runtimeEdges: [],
variables: {}, variables: {},
usagePush: vi.fn(), usagePush: vi.fn(),
lastInteractive: undefined lastInteractive: undefined,
checkIsStopping: () => false
} as any; } as any;
const result: any = await dispatchLoopRun(props); const result: any = await dispatchLoopRun(props);
...@@ -781,6 +787,7 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => { ...@@ -781,6 +787,7 @@ describe('runLoopRun (integration with mocked runWorkflow)', () => {
runtimeEdges: [], runtimeEdges: [],
variables: {}, variables: {},
usagePush: vi.fn(), usagePush: vi.fn(),
checkIsStopping: () => false,
lastInteractive: { lastInteractive: {
type: 'loopRunInteractive', type: 'loopRunInteractive',
params: { params: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment