fix(update): add a timeout for deployment/rebuild and add a cancel button.
This commit is contained in:
1 parent
c30f828d2c
commit
81622b5a4c
8 files changed
+443
-19
No files matched your search
@@ -234,6 +234,8 @@ export default function DeployContainerModal({
|
||||
const [networksLoading, setNetworksLoading] = useState(false);
|
||||
const [networksError, setNetworksError] = useState("");
|
||||
const envFileInputRef = useRef<HTMLInputElement | null>(null);
|
||||
const currentJobIdRef = useRef<string | null>(null);
|
||||
const cancelRequestedRef = useRef(false);
|
||||
const [uploadTargetEnvId, setUploadTargetEnvId] = useState<string | null>(
|
||||
null,
|
||||
);
|
||||
@@ -779,6 +781,8 @@ export default function DeployContainerModal({
|
||||
event.preventDefault();
|
||||
setError("");
|
||||
setLoading(true);
|
||||
currentJobIdRef.current = null;
|
||||
cancelRequestedRef.current = false;
|
||||
let processLogLines = [
|
||||
`[deploy] Starting deployment for ${form.name || "new container"}`,
|
||||
];
|
||||
@@ -946,6 +950,7 @@ export default function DeployContainerModal({
|
||||
|
||||
const jobResponse = await containersApi.createDeployJob(payload);
|
||||
const job = jobResponse.data;
|
||||
currentJobIdRef.current = job.id;
|
||||
let finalStatus = job.status;
|
||||
let finalError = job.error;
|
||||
|
||||
@@ -961,6 +966,33 @@ export default function DeployContainerModal({
|
||||
}),
|
||||
);
|
||||
|
||||
onProcessUpdate?.({
|
||||
cancelAction: {
|
||||
label: "Cancel",
|
||||
loadingLabel: "Cancelling",
|
||||
onClick: () => {
|
||||
const jobId = currentJobIdRef.current;
|
||||
if (!jobId || cancelRequestedRef.current) return;
|
||||
|
||||
cancelRequestedRef.current = true;
|
||||
onProcessUpdate?.({
|
||||
statusLabel: "Cancelling",
|
||||
cancelAction: {
|
||||
label: "Cancel",
|
||||
loadingLabel: "Cancelling",
|
||||
isLoading: true,
|
||||
disabled: true,
|
||||
onClick: () => undefined,
|
||||
},
|
||||
});
|
||||
|
||||
void containersApi
|
||||
.cancelJob(jobId)
|
||||
.catch(() => undefined);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await containersApi.streamJob(job.id, {
|
||||
onLog: (entry) => {
|
||||
updateProcessTerminal(
|
||||
@@ -977,10 +1009,25 @@ export default function DeployContainerModal({
|
||||
},
|
||||
});
|
||||
|
||||
if (cancelRequestedRef.current && finalStatus !== "cancelled") {
|
||||
const cancelledJob = currentJobIdRef.current
|
||||
? await containersApi.getJob(currentJobIdRef.current)
|
||||
: null;
|
||||
finalStatus = cancelledJob?.data.status ?? "cancelled";
|
||||
finalError =
|
||||
cancelledJob?.data.error ??
|
||||
cancelledJob?.data.cancelReason ??
|
||||
"Deployment cancelled";
|
||||
}
|
||||
|
||||
if (finalStatus === "error") {
|
||||
throw new Error(finalError || "Deployment job failed");
|
||||
}
|
||||
|
||||
if (finalStatus === "cancelled") {
|
||||
throw new Error(finalError || "Deployment cancelled");
|
||||
}
|
||||
|
||||
updateDeployTimelineModal({
|
||||
onProcessUpdate,
|
||||
activeStep: 3,
|
||||
@@ -1003,6 +1050,7 @@ export default function DeployContainerModal({
|
||||
"[deploy] Done",
|
||||
].filter(Boolean),
|
||||
});
|
||||
onProcessUpdate?.({ cancelAction: undefined });
|
||||
|
||||
onClose();
|
||||
} catch (err: unknown) {
|
||||
@@ -1013,7 +1061,9 @@ export default function DeployContainerModal({
|
||||
name: form.name,
|
||||
message,
|
||||
});
|
||||
onProcessUpdate?.({ cancelAction: undefined });
|
||||
} finally {
|
||||
currentJobIdRef.current = null;
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
+48
@@ -424,6 +424,8 @@ export default function AppContainerDetailPage() {
|
||||
closeProcessLogs,
|
||||
} = useProcessLogsModal();
|
||||
const containerRecordRef = useRef<Container | null>(null);
|
||||
const rebuildJobIdRef = useRef<string | null>(null);
|
||||
const rebuildCancelRequestedRef = useRef(false);
|
||||
const runtimeMetricsInFlightRef = useRef(false);
|
||||
const environmentContainersHref = `/projects/${params.projectId}/environments/${params.environmentId}`;
|
||||
const appDetailId = appDetail?.id;
|
||||
@@ -796,6 +798,8 @@ export default function AppContainerDetailPage() {
|
||||
setActing(true);
|
||||
setActiveAction("rebuild");
|
||||
setActionError("");
|
||||
rebuildJobIdRef.current = null;
|
||||
rebuildCancelRequestedRef.current = false;
|
||||
const baseTerminalLines = [
|
||||
`[rebuild] Starting rebuild for ${containerRecord.name}`,
|
||||
`[rebuild] Source: ${containerRecord.sourceType ?? "unknown"}`,
|
||||
@@ -841,6 +845,7 @@ export default function AppContainerDetailPage() {
|
||||
params.containerId,
|
||||
);
|
||||
const job = jobResponse.data;
|
||||
rebuildJobIdRef.current = job.id;
|
||||
let finalStatus = job.status;
|
||||
let finalError = job.error;
|
||||
|
||||
@@ -856,6 +861,31 @@ export default function AppContainerDetailPage() {
|
||||
},
|
||||
);
|
||||
|
||||
updateProcessLogs({
|
||||
cancelAction: {
|
||||
label: "Cancel",
|
||||
loadingLabel: "Cancelling",
|
||||
onClick: () => {
|
||||
const jobId = rebuildJobIdRef.current;
|
||||
if (!jobId || rebuildCancelRequestedRef.current) return;
|
||||
|
||||
rebuildCancelRequestedRef.current = true;
|
||||
updateProcessLogs({
|
||||
statusLabel: "Cancelling",
|
||||
cancelAction: {
|
||||
label: "Cancel",
|
||||
loadingLabel: "Cancelling",
|
||||
isLoading: true,
|
||||
disabled: true,
|
||||
onClick: () => undefined,
|
||||
},
|
||||
});
|
||||
|
||||
void containersApi.cancelJob(jobId).catch(() => undefined);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await containersApi.streamJob(job.id, {
|
||||
onLog: (entry) => {
|
||||
updateProcessTerminal([...latestTerminalLines, entry.message], {
|
||||
@@ -869,10 +899,25 @@ export default function AppContainerDetailPage() {
|
||||
},
|
||||
});
|
||||
|
||||
if (rebuildCancelRequestedRef.current && finalStatus !== "cancelled") {
|
||||
const cancelledJob = rebuildJobIdRef.current
|
||||
? await containersApi.getJob(rebuildJobIdRef.current)
|
||||
: null;
|
||||
finalStatus = cancelledJob?.data.status ?? "cancelled";
|
||||
finalError =
|
||||
cancelledJob?.data.error ??
|
||||
cancelledJob?.data.cancelReason ??
|
||||
"Rebuild cancelled";
|
||||
}
|
||||
|
||||
if (finalStatus === "error") {
|
||||
throw new Error(finalError || "Rebuild job failed");
|
||||
}
|
||||
|
||||
if (finalStatus === "cancelled") {
|
||||
throw new Error(finalError || "Rebuild cancelled");
|
||||
}
|
||||
|
||||
updateProcessLogs({
|
||||
timelineLogs: createRebuildTimeline(2),
|
||||
terminalLogs: [
|
||||
@@ -898,6 +943,7 @@ export default function AppContainerDetailPage() {
|
||||
].filter(Boolean),
|
||||
statusLabel: "100%",
|
||||
});
|
||||
updateProcessLogs({ cancelAction: undefined });
|
||||
} catch (rebuildError) {
|
||||
const message =
|
||||
rebuildError instanceof Error ? rebuildError.message : "Rebuild failed";
|
||||
@@ -911,7 +957,9 @@ export default function AppContainerDetailPage() {
|
||||
],
|
||||
statusLabel: "Failed",
|
||||
});
|
||||
updateProcessLogs({ cancelAction: undefined });
|
||||
} finally {
|
||||
rebuildJobIdRef.current = null;
|
||||
setActing(false);
|
||||
setActiveAction(null);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user