Make dev_server_start idempotent to prevent HMR breakage and 502s
This commit is contained in:
@@ -181,13 +181,9 @@ export default function PreviewTab() {
|
|||||||
const path = currentPath.startsWith("/")
|
const path = currentPath.startsWith("/")
|
||||||
? currentPath
|
? currentPath
|
||||||
: `/${currentPath}`;
|
: `/${currentPath}`;
|
||||||
// Add the refreshKey as a query param so the iframe completely remounts/refetches
|
setIframeSrc(`${base}${path}`);
|
||||||
// when the user hits the manual refresh button.
|
|
||||||
const urlObj = new URL(`${base}${path}`);
|
|
||||||
urlObj.searchParams.set("_refresh", refreshKey.toString());
|
|
||||||
setIframeSrc(urlObj.toString());
|
|
||||||
}
|
}
|
||||||
}, [primaryRunning?.url, currentPath, refreshKey]);
|
}, [primaryRunning?.url, currentPath]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!bridge || !iframeSrc || !iframeDomRef.current) return;
|
if (!bridge || !iframeSrc || !iframeDomRef.current) return;
|
||||||
|
|||||||
@@ -873,14 +873,36 @@ export async function startDevServer(
|
|||||||
// to keep the dashboard clean and prevent memory leaks.
|
// to keep the dashboard clean and prevent memory leaks.
|
||||||
const existingRows = await query<{
|
const existingRows = await query<{
|
||||||
id: string;
|
id: string;
|
||||||
pid: number | null;
|
project_id: string;
|
||||||
|
workspace: string;
|
||||||
|
name: string;
|
||||||
|
command: string;
|
||||||
port: number;
|
port: number;
|
||||||
|
pid: number | null;
|
||||||
|
preview_url: string;
|
||||||
|
state: "starting" | "running" | "stopped" | "failed";
|
||||||
|
started_at: string;
|
||||||
|
stopped_at: string | null;
|
||||||
}>(
|
}>(
|
||||||
`SELECT id, pid, port FROM fs_dev_servers
|
`SELECT * FROM fs_dev_servers
|
||||||
WHERE project_id = $1 AND state IN ('starting','running','failed')`,
|
WHERE project_id = $1 AND state IN ('starting','running','failed')`,
|
||||||
[opts.projectId],
|
[opts.projectId],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// IDEMPOTENCY: If the exact same command is already starting or running on the same port,
|
||||||
|
// do not kill it! Just return the existing record. This prevents the AI from accidentally
|
||||||
|
// bouncing the server and dropping the cache after every file edit, which leads to 502s.
|
||||||
|
const alreadyRunning = existingRows.find(
|
||||||
|
(r) =>
|
||||||
|
r.port === opts.port &&
|
||||||
|
r.command === opts.command &&
|
||||||
|
(r.state === "starting" || r.state === "running"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (alreadyRunning) {
|
||||||
|
return alreadyRunning;
|
||||||
|
}
|
||||||
|
|
||||||
const killPortNodeCmd =
|
const killPortNodeCmd =
|
||||||
`node -e '` +
|
`node -e '` +
|
||||||
`const fs = require("fs"); ` +
|
`const fs = require("fs"); ` +
|
||||||
|
|||||||
Reference in New Issue
Block a user