Jon/sky 6395 refresh code while workflow is running (#3444)
This commit is contained in:
@@ -143,7 +143,7 @@ function Workspace({
|
|||||||
? ""
|
? ""
|
||||||
: cacheKeyValueParam
|
: cacheKeyValueParam
|
||||||
? cacheKeyValueParam
|
? cacheKeyValueParam
|
||||||
: constructCacheKeyValue(cacheKey, workflow),
|
: constructCacheKeyValue({ codeKey: cacheKey, workflow }),
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { WorkflowApiResponse } from "@/routes/workflows/types/workflowTypes";
|
import { WorkflowApiResponse } from "@/routes/workflows/types/workflowTypes";
|
||||||
|
import { WorkflowRunStatusApiResponse } from "@/api/types";
|
||||||
import {
|
import {
|
||||||
isDisplayedInWorkflowEditor,
|
isDisplayedInWorkflowEditor,
|
||||||
WorkflowEditorParameterTypes,
|
WorkflowEditorParameterTypes,
|
||||||
@@ -113,23 +114,29 @@ const getInitialParameters = (workflow: WorkflowApiResponse) => {
|
|||||||
/**
|
/**
|
||||||
* Attempt to construct a valid code key value from the workflow parameters.
|
* Attempt to construct a valid code key value from the workflow parameters.
|
||||||
*/
|
*/
|
||||||
const constructCacheKeyValue = (
|
const constructCacheKeyValue = (opts: {
|
||||||
codeKey: string,
|
codeKey: string;
|
||||||
workflow?: WorkflowApiResponse,
|
workflow?: WorkflowApiResponse;
|
||||||
) => {
|
workflowRun?: WorkflowRunStatusApiResponse;
|
||||||
|
}) => {
|
||||||
|
const { workflow, workflowRun } = opts;
|
||||||
|
let codeKey = opts.codeKey;
|
||||||
|
|
||||||
if (!workflow) {
|
if (!workflow) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflowParameters = getInitialParameters(workflow)
|
const workflowParameters = workflowRun
|
||||||
.filter((p) => p.parameterType === "workflow")
|
? workflowRun?.parameters ?? {}
|
||||||
.reduce(
|
: getInitialParameters(workflow)
|
||||||
(acc, parameter) => {
|
.filter((p) => p.parameterType === "workflow")
|
||||||
acc[parameter.key] = parameter.defaultValue;
|
.reduce(
|
||||||
return acc;
|
(acc, parameter) => {
|
||||||
},
|
acc[parameter.key] = parameter.defaultValue;
|
||||||
{} as Record<string, unknown>,
|
return acc;
|
||||||
);
|
},
|
||||||
|
{} as Record<string, unknown>,
|
||||||
|
);
|
||||||
|
|
||||||
for (const [name, value] of Object.entries(workflowParameters)) {
|
for (const [name, value] of Object.entries(workflowParameters)) {
|
||||||
if (value === null || value === undefined || value === "") {
|
if (value === null || value === undefined || value === "") {
|
||||||
|
|||||||
@@ -7,17 +7,25 @@ type Props = {
|
|||||||
cacheKey?: string;
|
cacheKey?: string;
|
||||||
cacheKeyValue?: string;
|
cacheKeyValue?: string;
|
||||||
workflowPermanentId?: string;
|
workflowPermanentId?: string;
|
||||||
|
pollIntervalMs?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
function useBlockScriptsQuery({
|
function useBlockScriptsQuery({
|
||||||
cacheKey,
|
cacheKey,
|
||||||
cacheKeyValue,
|
cacheKeyValue,
|
||||||
workflowPermanentId,
|
workflowPermanentId,
|
||||||
|
pollIntervalMs,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const credentialGetter = useCredentialGetter();
|
const credentialGetter = useCredentialGetter();
|
||||||
|
|
||||||
return useQuery<{ [blockName: string]: string }>({
|
return useQuery<{ [blockName: string]: string }>({
|
||||||
queryKey: ["block-scripts", workflowPermanentId, cacheKey, cacheKeyValue],
|
queryKey: [
|
||||||
|
"block-scripts",
|
||||||
|
workflowPermanentId,
|
||||||
|
cacheKey,
|
||||||
|
cacheKeyValue,
|
||||||
|
pollIntervalMs,
|
||||||
|
],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const client = await getClient(credentialGetter, "sans-api-v1");
|
const client = await getClient(credentialGetter, "sans-api-v1");
|
||||||
|
|
||||||
@@ -30,6 +38,12 @@ function useBlockScriptsQuery({
|
|||||||
|
|
||||||
return result.blocks;
|
return result.blocks;
|
||||||
},
|
},
|
||||||
|
refetchInterval: () => {
|
||||||
|
if (!pollIntervalMs || pollIntervalMs === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Math.max(2000, pollIntervalMs);
|
||||||
|
},
|
||||||
enabled: !!workflowPermanentId,
|
enabled: !!workflowPermanentId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ import {
|
|||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||||
|
import { statusIsFinalized } from "@/routes/tasks/types";
|
||||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||||
import { useBlockScriptsQuery } from "@/routes/workflows/hooks/useBlockScriptsQuery";
|
import { useBlockScriptsQuery } from "@/routes/workflows/hooks/useBlockScriptsQuery";
|
||||||
import { useCacheKeyValuesQuery } from "@/routes/workflows/hooks/useCacheKeyValuesQuery";
|
import { useCacheKeyValuesQuery } from "@/routes/workflows/hooks/useCacheKeyValuesQuery";
|
||||||
import { useWorkflowQuery } from "@/routes/workflows/hooks/useWorkflowQuery";
|
import { useWorkflowQuery } from "@/routes/workflows/hooks/useWorkflowQuery";
|
||||||
|
import { useWorkflowRunQuery } from "@/routes/workflows/hooks/useWorkflowRunQuery";
|
||||||
import { constructCacheKeyValue } from "@/routes/workflows/editor/utils";
|
import { constructCacheKeyValue } from "@/routes/workflows/editor/utils";
|
||||||
import { WorkflowApiResponse } from "@/routes/workflows/types/workflowTypes";
|
import { WorkflowApiResponse } from "@/routes/workflows/types/workflowTypes";
|
||||||
|
|
||||||
@@ -72,12 +74,15 @@ function WorkflowRunCode(props?: Props) {
|
|||||||
const showCacheKeyValueSelector = props?.showCacheKeyValueSelector ?? false;
|
const showCacheKeyValueSelector = props?.showCacheKeyValueSelector ?? false;
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { workflowPermanentId } = useParams();
|
const { workflowPermanentId } = useParams();
|
||||||
|
const { data: workflowRun } = useWorkflowRunQuery();
|
||||||
const { data: workflow } = useWorkflowQuery({
|
const { data: workflow } = useWorkflowQuery({
|
||||||
workflowPermanentId,
|
workflowPermanentId,
|
||||||
});
|
});
|
||||||
const cacheKey = workflow?.cache_key ?? "";
|
const cacheKey = workflow?.cache_key ?? "";
|
||||||
const [cacheKeyValue, setCacheKeyValue] = useState(
|
const [cacheKeyValue, setCacheKeyValue] = useState(
|
||||||
cacheKey === "" ? "" : constructCacheKeyValue(cacheKey, workflow),
|
cacheKey === ""
|
||||||
|
? ""
|
||||||
|
: constructCacheKeyValue({ codeKey: cacheKey, workflow, workflowRun }),
|
||||||
);
|
);
|
||||||
const { data: cacheKeyValues } = useCacheKeyValuesQuery({
|
const { data: cacheKeyValues } = useCacheKeyValuesQuery({
|
||||||
cacheKey,
|
cacheKey,
|
||||||
@@ -85,13 +90,25 @@ function WorkflowRunCode(props?: Props) {
|
|||||||
page: 1,
|
page: 1,
|
||||||
workflowPermanentId,
|
workflowPermanentId,
|
||||||
});
|
});
|
||||||
|
const isFinalized = workflowRun ? statusIsFinalized(workflowRun) : null;
|
||||||
|
const parameters = workflowRun?.parameters;
|
||||||
|
|
||||||
|
const { data: blockScripts } = useBlockScriptsQuery({
|
||||||
|
cacheKey,
|
||||||
|
cacheKeyValue,
|
||||||
|
workflowPermanentId,
|
||||||
|
pollIntervalMs: !isFinalized ? 3000 : undefined,
|
||||||
|
});
|
||||||
|
const orderedBlockLabels = getOrderedBlockLabels(workflow);
|
||||||
|
const code = getCode(orderedBlockLabels, blockScripts).join("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCacheKeyValue(
|
setCacheKeyValue(
|
||||||
cacheKeyValues?.values[0] ?? constructCacheKeyValue(cacheKey, workflow),
|
constructCacheKeyValue({ codeKey: cacheKey, workflow, workflowRun }) ??
|
||||||
|
cacheKeyValues?.values[0],
|
||||||
);
|
);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [cacheKeyValues, setCacheKeyValue, workflow]);
|
}, [cacheKeyValues, parameters, setCacheKeyValue, workflow, workflowRun]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
@@ -104,16 +121,13 @@ function WorkflowRunCode(props?: Props) {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [workflow]);
|
}, [queryClient, workflow]);
|
||||||
|
|
||||||
const { data: blockScripts } = useBlockScriptsQuery({
|
useEffect(() => {
|
||||||
cacheKey,
|
queryClient.invalidateQueries({
|
||||||
cacheKeyValue,
|
queryKey: ["block-scripts", workflowPermanentId, cacheKey, cacheKeyValue],
|
||||||
workflowPermanentId,
|
});
|
||||||
});
|
}, [queryClient, workflowRun, workflowPermanentId, cacheKey, cacheKeyValue]);
|
||||||
|
|
||||||
const orderedBlockLabels = getOrderedBlockLabels(workflow);
|
|
||||||
const code = getCode(orderedBlockLabels, blockScripts).join("");
|
|
||||||
|
|
||||||
if (code.length === 0) {
|
if (code.length === 0) {
|
||||||
return (
|
return (
|
||||||
@@ -123,10 +137,7 @@ function WorkflowRunCode(props?: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (!showCacheKeyValueSelector || !cacheKey || cacheKey === "") {
|
||||||
!showCacheKeyValueSelector ||
|
|
||||||
(cacheKeyValues?.values ?? []).length <= 1
|
|
||||||
) {
|
|
||||||
return (
|
return (
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
className="h-full overflow-y-scroll"
|
className="h-full overflow-y-scroll"
|
||||||
@@ -139,14 +150,33 @@ function WorkflowRunCode(props?: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cacheKeyValueSet = new Set([...(cacheKeyValues?.values ?? [])]);
|
||||||
|
|
||||||
|
const cacheKeyValueForWorkflowRun = constructCacheKeyValue({
|
||||||
|
codeKey: cacheKey,
|
||||||
|
workflow,
|
||||||
|
workflowRun,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cacheKeyValueForWorkflowRun) {
|
||||||
|
cacheKeyValueSet.add(cacheKeyValueForWorkflowRun);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col items-end justify-center gap-2">
|
<div className="flex h-full w-full flex-col items-end justify-center gap-2">
|
||||||
<div className="flex w-[20rem] gap-4">
|
<div className="flex w-[20rem] gap-4">
|
||||||
<div className="flex items-center justify-around gap-2">
|
<div className="flex items-center justify-around gap-2">
|
||||||
<Label className="w-[7rem]">Code Cache Key</Label>
|
<Label className="w-[7rem]">Code Key Value</Label>
|
||||||
<HelpTooltip content="Which generated (& cached) code to view." />
|
<HelpTooltip
|
||||||
|
content={
|
||||||
|
!isFinalized
|
||||||
|
? "The code key value the generated code is being stored under."
|
||||||
|
: "Which generated (& cached) code to view."
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
|
disabled={!isFinalized}
|
||||||
value={cacheKeyValue}
|
value={cacheKeyValue}
|
||||||
onValueChange={(v: string) => setCacheKeyValue(v)}
|
onValueChange={(v: string) => setCacheKeyValue(v)}
|
||||||
>
|
>
|
||||||
@@ -154,13 +184,20 @@ function WorkflowRunCode(props?: Props) {
|
|||||||
<SelectValue placeholder="Code Key Value" />
|
<SelectValue placeholder="Code Key Value" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(cacheKeyValues?.values ?? []).map((value) => {
|
{Array.from(cacheKeyValueSet)
|
||||||
return (
|
.sort()
|
||||||
<SelectItem key={value} value={value}>
|
.map((value) => {
|
||||||
{value}
|
return (
|
||||||
</SelectItem>
|
<SelectItem key={value} value={value}>
|
||||||
);
|
{value === cacheKeyValueForWorkflowRun &&
|
||||||
})}
|
isFinalized === true ? (
|
||||||
|
<span className="underline">{value}</span>
|
||||||
|
) : (
|
||||||
|
value
|
||||||
|
)}
|
||||||
|
</SelectItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user