feat(cms): improve catalog, editorial recovery and operations
This commit is contained in:
1 parent
2fead134e6
commit
c389c3893d
122 files changed
+8137
-703
No files matched your search
@@ -0,0 +1,111 @@
|
||||
import "server-only";
|
||||
import { constants } from "node:fs";
|
||||
import { access, readdir } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { sql } from "drizzle-orm";
|
||||
import {
|
||||
type DiagnosticState,
|
||||
migrationState,
|
||||
workerState,
|
||||
} from "@/lib/admin/installation-state";
|
||||
import { fetchOpsHealth } from "@/lib/admin/ops-health";
|
||||
import { db } from "@/lib/db";
|
||||
import { redis } from "@/lib/redis";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
export async function inspectInstallation() {
|
||||
const started = performance.now();
|
||||
const [health, storage, expected, applied, heartbeat, renderer] =
|
||||
await Promise.all([
|
||||
fetchOpsHealth(),
|
||||
Promise.all(
|
||||
["storage", "public/nitro-assets", "public/swf"].map(async (name) => ({
|
||||
name,
|
||||
state: await access(
|
||||
path.join(process.cwd(), name),
|
||||
constants.R_OK | constants.W_OK,
|
||||
)
|
||||
.then(() => "ok" as const)
|
||||
.catch(() => "failed" as const),
|
||||
})),
|
||||
),
|
||||
readdir(path.join(process.cwd(), "drizzle/migrations"))
|
||||
.then((files) =>
|
||||
files
|
||||
.filter((name) => name.endsWith(".sql"))
|
||||
.map((name) => name.slice(0, -4)),
|
||||
)
|
||||
.catch(() => []),
|
||||
db
|
||||
.execute(sql`SELECT migration FROM cms_migrations`)
|
||||
.then(([rows]) =>
|
||||
(rows as unknown as { migration: string }[]).map(
|
||||
(row) => row.migration,
|
||||
),
|
||||
)
|
||||
.catch(() => null),
|
||||
redis
|
||||
? redis.get("cms:jobs-worker:heartbeat").catch(() => null)
|
||||
: Promise.resolve(null),
|
||||
siteSettings.get("nitro_client_url", "").catch(() => ""),
|
||||
]);
|
||||
const migration = migrationState(expected, applied);
|
||||
const release = process.env.NEXT_PUBLIC_CMS_RELEASE ?? "unknown";
|
||||
const rows: Array<{ key: string; state: DiagnosticState; detail?: string }> =
|
||||
[
|
||||
{
|
||||
key: "release",
|
||||
state: /^[a-f0-9]{40}$/i.test(release) ? "ok" : "unknown",
|
||||
detail: /^[a-f0-9]{40}$/i.test(release) ? release : undefined,
|
||||
},
|
||||
{
|
||||
key: "database",
|
||||
state: health.dbOk ? "ok" : "failed",
|
||||
detail: health.dbOk ? `${health.dbLatencyMs} ms` : undefined,
|
||||
},
|
||||
{
|
||||
key: "redis",
|
||||
state:
|
||||
health.redisOk === null
|
||||
? "missing"
|
||||
: health.redisOk
|
||||
? "ok"
|
||||
: "failed",
|
||||
},
|
||||
{ key: "emulator", state: health.emulatorOk ? "ok" : "failed" },
|
||||
{
|
||||
key: "storage",
|
||||
state: storage.every((item) => item.state === "ok") ? "ok" : "failed",
|
||||
detail:
|
||||
storage
|
||||
.filter((item) => item.state !== "ok")
|
||||
.map((item) => item.name)
|
||||
.join(", ") || undefined,
|
||||
},
|
||||
{
|
||||
key: "migrations",
|
||||
state: migration.state,
|
||||
detail:
|
||||
migration.pending === null ? undefined : String(migration.pending),
|
||||
},
|
||||
{
|
||||
key: "worker",
|
||||
state: workerState(heartbeat),
|
||||
detail:
|
||||
heartbeat && Number.isFinite(Date.parse(heartbeat))
|
||||
? new Date(heartbeat).toISOString()
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
key: "renderer",
|
||||
state: health.dbOk ? "ok" : "unknown",
|
||||
detail: health.dbOk && !renderer ? "/nitro-client/" : undefined,
|
||||
},
|
||||
{ key: "registry", state: "unknown" },
|
||||
];
|
||||
return {
|
||||
rows,
|
||||
checkedAt: new Date().toISOString(),
|
||||
durationMs: Math.round(performance.now() - started),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user