feat: add http node timeout (#2465)

* fix $ in replacement string misinterpreted as regex special character

* add http timeout

* delete console log
This commit is contained in:
heheer
2024-08-21 20:23:35 +08:00
committed by GitHub
parent 113c57bcbe
commit 5627a4bfde
7 changed files with 90 additions and 10 deletions

View File

@@ -105,6 +105,7 @@ export enum NodeInputKeyEnum {
httpMethod = 'system_httpMethod', httpMethod = 'system_httpMethod',
httpParams = 'system_httpParams', httpParams = 'system_httpParams',
httpJsonBody = 'system_httpJsonBody', httpJsonBody = 'system_httpJsonBody',
httpTimeout = 'system_httpTimeout',
abandon_httpUrl = 'url', abandon_httpUrl = 'url',
// app // app

View File

@@ -44,6 +44,16 @@ export const HttpNode468: FlowNodeTemplateType = {
value: 'POST', value: 'POST',
required: true required: true
}, },
{
key: NodeInputKeyEnum.httpTimeout,
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.number,
label: '',
value: 120,
min: 30,
max: 600,
required: true
},
{ {
key: NodeInputKeyEnum.httpReqUrl, key: NodeInputKeyEnum.httpReqUrl,
renderTypeList: [FlowNodeInputTypeEnum.hidden], renderTypeList: [FlowNodeInputTypeEnum.hidden],

View File

@@ -57,6 +57,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
system_httpHeader: httpHeader, system_httpHeader: httpHeader,
system_httpParams: httpParams = [], system_httpParams: httpParams = [],
system_httpJsonBody: httpJsonBody, system_httpJsonBody: httpJsonBody,
system_httpTimeout: httpTimeout,
[NodeInputKeyEnum.addInputParam]: dynamicInput, [NodeInputKeyEnum.addInputParam]: dynamicInput,
...body ...body
} }
@@ -143,7 +144,8 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
url: httpReqUrl, url: httpReqUrl,
headers, headers,
body: requestBody, body: requestBody,
params params,
timeout: httpTimeout
}); });
})(); })();
@@ -199,13 +201,15 @@ async function fetchData({
url, url,
headers, headers,
body, body,
params params,
timeout
}: { }: {
method: string; method: string;
url: string; url: string;
headers: Record<string, any>; headers: Record<string, any>;
body: Record<string, any> | string; body: Record<string, any> | string;
params: Record<string, any>; params: Record<string, any>;
timeout: number;
}) { }) {
const { data: response } = await axios({ const { data: response } = await axios({
method, method,
@@ -215,7 +219,7 @@ async function fetchData({
'Content-Type': 'application/json', 'Content-Type': 'application/json',
...headers ...headers
}, },
timeout: 120000, timeout: timeout * 1000,
params: params, params: params,
data: ['POST', 'PUT', 'PATCH'].includes(method) ? body : undefined data: ['POST', 'PUT', 'PATCH'].includes(method) ? body : undefined
}); });
@@ -308,7 +312,7 @@ function replaceVariable(text: string, obj: Record<string, any>) {
replacement.startsWith('"') && replacement.endsWith('"') replacement.startsWith('"') && replacement.endsWith('"')
? replacement.slice(1, -1) ? replacement.slice(1, -1)
: replacement; : replacement;
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), unquotedReplacement); text = text.replace(new RegExp(`{{(${key})}}`, 'g'), () => unquotedReplacement);
} }
} }
return text || ''; return text || '';

View File

@@ -617,7 +617,8 @@
"success": "Start syncing" "success": "Start syncing"
} }
}, },
"training": {} "training": {
}
}, },
"data": { "data": {
"Auxiliary Data": "Auxiliary data", "Auxiliary Data": "Auxiliary data",
@@ -795,6 +796,7 @@
"Field Name": "Field name", "Field Name": "Field name",
"Http request props": "Request parameters", "Http request props": "Request parameters",
"Http request settings": "Request settings", "Http request settings": "Request settings",
"Http timeout": "Timeout",
"Input Type": "Input type", "Input Type": "Input type",
"Laf sync params": "Synchronize parameters", "Laf sync params": "Synchronize parameters",
"Max Length": "Maximum length", "Max Length": "Maximum length",

View File

@@ -617,7 +617,8 @@
"success": "开始同步" "success": "开始同步"
} }
}, },
"training": {} "training": {
}
}, },
"data": { "data": {
"Auxiliary Data": "辅助数据", "Auxiliary Data": "辅助数据",
@@ -795,6 +796,7 @@
"Field Name": "字段名", "Field Name": "字段名",
"Http request props": "请求参数", "Http request props": "请求参数",
"Http request settings": "请求配置", "Http request settings": "请求配置",
"Http timeout": "超时时长",
"Input Type": "输入类型", "Input Type": "输入类型",
"Laf sync params": "同步参数", "Laf sync params": "同步参数",
"Max Length": "最大长度", "Max Length": "最大长度",
@@ -993,7 +995,6 @@
"Edit Folder": "编辑文件夹", "Edit Folder": "编辑文件夹",
"Edit Info": "编辑信息", "Edit Info": "编辑信息",
"Export": "导出", "Export": "导出",
"dataset_name": "知识库名称",
"Export Dataset Limit Error": "导出数据失败", "Export Dataset Limit Error": "导出数据失败",
"Folder Name": "输入文件夹名称", "Folder Name": "输入文件夹名称",
"Insert Data": "插入", "Insert Data": "插入",
@@ -1031,6 +1032,7 @@
}, },
"input is empty": "数据内容不能为空 " "input is empty": "数据内容不能为空 "
}, },
"dataset_name": "知识库名称",
"deleteFolderTips": "确认删除该文件夹及其包含的所有知识库?删除后数据无法恢复,请确认!", "deleteFolderTips": "确认删除该文件夹及其包含的所有知识库?删除后数据无法恢复,请确认!",
"test": { "test": {
"noResult": "搜索结果为空" "noResult": "搜索结果为空"

View File

@@ -92,7 +92,6 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
const { data: basicNodes } = useRequest2( const { data: basicNodes } = useRequest2(
async () => { async () => {
if (templateType === TemplateTypeEnum.basic) { if (templateType === TemplateTypeEnum.basic) {
console.log(1111);
return basicNodeTemplates return basicNodeTemplates
.filter((item) => { .filter((item) => {
// unique node filter // unique node filter

View File

@@ -17,7 +17,12 @@ import {
Td, Td,
TableContainer, TableContainer,
Button, Button,
useDisclosure useDisclosure,
NumberInputField,
NumberInputStepper,
NumberIncrementStepper,
NumberDecrementStepper,
NumberInput
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
@@ -372,6 +377,61 @@ export function RenderHttpProps({
return Render; return Render;
} }
const RenderHttpTimeout = ({
nodeId,
inputs
}: {
nodeId: string;
inputs: FlowNodeInputItemType[];
}) => {
const { t } = useTranslation();
const timeout = inputs.find((item) => item.key === NodeInputKeyEnum.httpTimeout)!;
const [isEditTimeout, setIsEditTimeout] = useState(false);
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
return (
<Box>
<Box mb={2} display={'flex'} justifyContent={'space-between'}>
<Box fontWeight={'medium'} color={'myGray.600'}>
{t('common:core.module.Http timeout')}
</Box>
<Box>
{isEditTimeout ? (
<NumberInput
defaultValue={timeout.value}
min={timeout.min}
max={timeout.max}
onBlur={() => setIsEditTimeout(false)}
onChange={(e) => {
onChangeNode({
nodeId,
type: 'updateInput',
key: NodeInputKeyEnum.httpTimeout,
value: {
...timeout,
value: Number(e)
}
});
}}
>
<NumberInputField bg={'white'} px={3} borderRadius={'sm'} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
) : (
<Button
variant={'ghost'}
color={'myGray.600'}
onClick={() => setIsEditTimeout(true)}
>{`${timeout?.value} s`}</Button>
)}
</Box>
</Box>
</Box>
);
};
const RenderForm = ({ const RenderForm = ({
nodeId, nodeId,
input, input,
@@ -643,11 +703,13 @@ const NodeHttp = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
<RenderHttpMethodAndUrl nodeId={nodeId} inputs={inputs} /> <RenderHttpMethodAndUrl nodeId={nodeId} inputs={inputs} />
)); ));
const Headers = useMemoizedFn(() => <RenderHttpProps nodeId={nodeId} inputs={inputs} />); const Headers = useMemoizedFn(() => <RenderHttpProps nodeId={nodeId} inputs={inputs} />);
const HttpTimeout = useMemoizedFn(() => <RenderHttpTimeout nodeId={nodeId} inputs={inputs} />);
const CustomComponents = useMemo(() => { const CustomComponents = useMemo(() => {
return { return {
[NodeInputKeyEnum.httpMethod]: HttpMethodAndUrl, [NodeInputKeyEnum.httpMethod]: HttpMethodAndUrl,
[NodeInputKeyEnum.httpHeaders]: Headers [NodeInputKeyEnum.httpHeaders]: Headers,
[NodeInputKeyEnum.httpTimeout]: HttpTimeout
}; };
}, [Headers, HttpMethodAndUrl]); }, [Headers, HttpMethodAndUrl]);