rebuild the frontend without restarting, and restart when you must
Settings → System → Maintenance. Two buttons that are deliberately not a pair. ── Rebuild: real, and free ── The same `rebuildFrontend` a plugin install already runs. `Bun.build` reads source from disk on every call and writes `build/`, and the server serves that directory by reading each file per request — so a rebuild lands on the next page load with no process restart, no dropped websocket and no chat session lost. ── Restart: the only way to load server code, and it costs ── Bun caches modules for the life of the process. Measured rather than assumed: editing a file and re-importing returns the ORIGINAL export, and a cache-busting query picks up that one specifier while everything it imports stays cached. So `rebuildHonoApp` — which install already does — re-wires the same module instances into a new tree and cannot see a backend edit. Busting the whole graph would duplicate singletons: two database clients, two session maps, one process. There is therefore no third button, and the screen says why. A "remount the API" control would look like it reloaded the backend and would not. The restart answers BEFORE it schedules itself, because the process serving that request is the one being replaced. It refuses outright when PM2 does not know this process — in development the platform runs under `bun --watch`, where the restart would fail into a promise nobody awaits while the button reported success. Verified: `POST /rebuild-frontend` → 200, 3.0s, 3 outputs; anonymous → 401. The restart button is deliberately untested from here — pressing it would end the session this was written in, which is the same reason it needs a label that says so. tsgo clean, frontend builds, 914 pass / 7 fail unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,22 @@ export async function startProcess(name: string, cwd: string): Promise<Pm2Result
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart a process that PM2 already knows.
|
||||
*
|
||||
* Used by the owner's "restart the server" button, where the target is `officer` itself — the process
|
||||
* making this very call. PM2 replaces it, so nothing after the spawn in this process is guaranteed to
|
||||
* run, and the caller must have been answered already.
|
||||
*
|
||||
* `restart` rather than stop-then-start: PM2 keeps the entry, the restart counter and the log stream
|
||||
* continuous, and there is no window in which the process is absent from `pm2 list` and looks uninstalled.
|
||||
*/
|
||||
export async function restartProcess(name: string, cwd: string): Promise<Pm2Result> {
|
||||
const { code, out } = await pm2(['restart', name], cwd);
|
||||
if (code !== 0) return { ok: false, error: out || `pm2 restart ${name} exited ${code}` };
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop it, leaving it in PM2's list.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user