Poc lambda deployment duration (#10340)
closes https://github.com/twentyhq/core-team-issues/issues/436 ## Acheivements Improve aws lambda deployment time from ~10/15 secs to less that 1 sec ## Done - migrate with the new code executor architecture for local and lambda drivers - support old and new executor architecture to avoid breaking changes - first run is long, next runs are quick even if code step is updated ## Demo using `lambda` driver ### Before https://github.com/user-attachments/assets/7f7664b4-658f-4689-8949-ea2c31131252 ### After https://github.com/user-attachments/assets/d486c8e2-f8f8-4dbd-a801-c9901e440b29
This commit is contained in:
@ -9,7 +9,6 @@ import {
|
||||
IconSquareRoundedCheck,
|
||||
IconSquareRoundedX,
|
||||
IconLoader,
|
||||
IconSettings,
|
||||
AnimatedCircleLoading,
|
||||
} from 'twenty-ui';
|
||||
import { ServerlessFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
||||
@ -41,11 +40,9 @@ const StyledOutput = styled.div<{ accent?: OutputAccent }>`
|
||||
export const ServerlessFunctionExecutionResult = ({
|
||||
serverlessFunctionTestData,
|
||||
isTesting = false,
|
||||
isBuilding = false,
|
||||
}: {
|
||||
serverlessFunctionTestData: ServerlessFunctionTestData;
|
||||
isTesting?: boolean;
|
||||
isBuilding?: boolean;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
@ -70,23 +67,17 @@ export const ServerlessFunctionExecutionResult = ({
|
||||
|
||||
const IdleLeftNode = 'Output';
|
||||
|
||||
const PendingLeftNode = (isTesting || isBuilding) && (
|
||||
const PendingLeftNode = isTesting && (
|
||||
<StyledOutput>
|
||||
<AnimatedCircleLoading>
|
||||
{isTesting ? (
|
||||
<IconLoader size={theme.icon.size.md} />
|
||||
) : (
|
||||
<IconSettings size={theme.icon.size.md} />
|
||||
)}
|
||||
<IconLoader size={theme.icon.size.md} />
|
||||
</AnimatedCircleLoading>
|
||||
<StyledInfoContainer>
|
||||
{isTesting ? 'Running function' : 'Building function'}
|
||||
</StyledInfoContainer>
|
||||
<StyledInfoContainer>Running function</StyledInfoContainer>
|
||||
</StyledOutput>
|
||||
);
|
||||
|
||||
const computeLeftNode = () => {
|
||||
if (isTesting || isBuilding) {
|
||||
if (isTesting) {
|
||||
return PendingLeftNode;
|
||||
}
|
||||
if (
|
||||
@ -115,7 +106,7 @@ export const ServerlessFunctionExecutionResult = ({
|
||||
language={serverlessFunctionTestData.language}
|
||||
height={serverlessFunctionTestData.height}
|
||||
options={{ readOnly: true, domReadOnly: true }}
|
||||
isLoading={isTesting || isBuilding}
|
||||
isLoading={isTesting}
|
||||
withHeader
|
||||
/>
|
||||
</StyledContainer>
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { useBuildDraftServerlessFunction } from '@/settings/serverless-functions/hooks/useBuildDraftServerlessFunction';
|
||||
import { useExecuteOneServerlessFunction } from '@/settings/serverless-functions/hooks/useExecuteOneServerlessFunction';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/states/serverlessFunctionTestDataFamilyState';
|
||||
import { useState } from 'react';
|
||||
@ -14,21 +13,12 @@ export const useTestServerlessFunction = ({
|
||||
callback?: (testResult: object) => void;
|
||||
}) => {
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
const [isBuilding, setIsBuilding] = useState(false);
|
||||
const { executeOneServerlessFunction } = useExecuteOneServerlessFunction();
|
||||
const { buildDraftServerlessFunction } = useBuildDraftServerlessFunction();
|
||||
const [serverlessFunctionTestData, setServerlessFunctionTestData] =
|
||||
useRecoilState(serverlessFunctionTestDataFamilyState(serverlessFunctionId));
|
||||
|
||||
const testServerlessFunction = async (shouldBuild = true) => {
|
||||
const testServerlessFunction = async () => {
|
||||
try {
|
||||
if (shouldBuild) {
|
||||
setIsBuilding(true);
|
||||
await buildDraftServerlessFunction({
|
||||
id: serverlessFunctionId,
|
||||
});
|
||||
setIsBuilding(false);
|
||||
}
|
||||
setIsTesting(true);
|
||||
await sleep(200); // Delay artificially to avoid flashing the UI
|
||||
const result = await executeOneServerlessFunction({
|
||||
@ -67,11 +57,10 @@ export const useTestServerlessFunction = ({
|
||||
},
|
||||
}));
|
||||
} catch (error) {
|
||||
setIsBuilding(false);
|
||||
setIsTesting(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
return { testServerlessFunction, isTesting, isBuilding };
|
||||
return { testServerlessFunction, isTesting };
|
||||
};
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
|
||||
export const BUILD_DRAFT_SERVERLESS_FUNCTION = gql`
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
mutation BuildDraftServerlessFunction(
|
||||
$input: BuildDraftServerlessFunctionInput!
|
||||
) {
|
||||
buildDraftServerlessFunction(input: $input) {
|
||||
...ServerlessFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,29 +0,0 @@
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { BUILD_DRAFT_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/buildDraftServerlessFunction';
|
||||
import {
|
||||
BuildDraftServerlessFunctionMutation,
|
||||
BuildDraftServerlessFunctionMutationVariables,
|
||||
BuildDraftServerlessFunctionInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useBuildDraftServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const [mutate] = useMutation<
|
||||
BuildDraftServerlessFunctionMutation,
|
||||
BuildDraftServerlessFunctionMutationVariables
|
||||
>(BUILD_DRAFT_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const buildDraftServerlessFunction = async (
|
||||
input: BuildDraftServerlessFunctionInput,
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
});
|
||||
};
|
||||
return { buildDraftServerlessFunction };
|
||||
};
|
||||
@ -81,8 +81,6 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
}: WorkflowEditActionFormServerlessFunctionProps) => {
|
||||
const theme = useTheme();
|
||||
const { getIcon } = useIcons();
|
||||
const [shouldBuildServerlessFunction, setShouldBuildServerlessFunction] =
|
||||
useState(false);
|
||||
const serverlessFunctionId = action.settings.input.serverlessFunctionId;
|
||||
const serverlessFunctionVersion =
|
||||
action.settings.input.serverlessFunctionVersion;
|
||||
@ -123,14 +121,12 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
});
|
||||
};
|
||||
|
||||
const { testServerlessFunction, isTesting, isBuilding } =
|
||||
useTestServerlessFunction({
|
||||
serverlessFunctionId,
|
||||
callback: updateOutputSchemaFromTestResult,
|
||||
});
|
||||
const { testServerlessFunction, isTesting } = useTestServerlessFunction({
|
||||
serverlessFunctionId,
|
||||
callback: updateOutputSchemaFromTestResult,
|
||||
});
|
||||
|
||||
const handleSave = useDebouncedCallback(async () => {
|
||||
setShouldBuildServerlessFunction(true);
|
||||
await updateOneServerlessFunction({
|
||||
name: formValues.name,
|
||||
description: formValues.description,
|
||||
@ -238,8 +234,7 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
}
|
||||
|
||||
if (!isTesting) {
|
||||
await testServerlessFunction(shouldBuildServerlessFunction);
|
||||
setShouldBuildServerlessFunction(false);
|
||||
await testServerlessFunction();
|
||||
}
|
||||
};
|
||||
|
||||
@ -348,7 +343,6 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
<InputLabel>Result</InputLabel>
|
||||
<ServerlessFunctionExecutionResult
|
||||
serverlessFunctionTestData={serverlessFunctionTestData}
|
||||
isBuilding={isBuilding}
|
||||
isTesting={isTesting}
|
||||
/>
|
||||
</StyledCodeEditorContainer>
|
||||
@ -361,7 +355,7 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
<CmdEnterActionButton
|
||||
title="Test"
|
||||
onClick={handleRunFunction}
|
||||
disabled={isTesting || isBuilding || actionOptions.readonly}
|
||||
disabled={isTesting || actionOptions.readonly}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user