feat(updater): support updates after verified SeaweedFS migration

This commit is contained in:
2026-09-28 15:47:06 +02:00
parent 790f20b499
commit 2b947c5e8f
20 changed files with 1074 additions and 67 deletions

View File

@@ -1,4 +1,7 @@
import { FastifyInstance } from "fastify"
import { HeadBucketCommand } from "@aws-sdk/client-s3"
import { s3 } from "../utils/s3"
import { secrets } from "../utils/secrets"
type MetricSample = {
labels: Record<string, string>
@@ -10,9 +13,6 @@ const metricLinePattern = /^([a-zA-Z_:][a-zA-Z0-9_:]*)(?:\{([^}]*)\})?\s+(-?(?:\
const nodeExporterUrl = () =>
(process.env.NODE_EXPORTER_URL || "http://node-exporter:9100").replace(/\/+$/, "")
const s3EndpointUrl = () =>
(process.env.S3_ENDPOINT || "").replace(/\/+$/, "")
const parseLabels = (value = "") => {
const labels: Record<string, string> = {}
const labelPattern = /(\w+)="((?:\\"|[^"])*)"/g
@@ -63,20 +63,17 @@ const serviceState = (ok: boolean, detail?: Record<string, any>) => ({
...detail,
})
const checkHttp = async (url: string, timeoutMs = 3000) => {
export const checkFileStorage = async (client = s3, bucket = secrets.S3_BUCKET, timeoutMs = 3000) => {
const controller = new AbortController()
const timeout = setTimeout(() => controller.abort(), timeoutMs)
try {
const response = await fetch(url, { signal: controller.signal })
return serviceState(response.ok, {
httpStatus: response.status,
url,
})
} catch (err: any) {
if (!client || !bucket) return serviceState(false, { error: "S3-Dateispeicher ist nicht eingerichtet" })
await client.send(new HeadBucketCommand({ Bucket: bucket }), { abortSignal: controller.signal })
return serviceState(true, { provider: process.env.FEDEO_STORAGE_PROVIDER === "seaweedfs" ? "seaweedfs" : "s3" })
} catch {
return serviceState(false, {
url,
error: err?.message || "HTTP-Abfrage fehlgeschlagen",
error: controller.signal.aborted ? "S3-Prüfung hat das Zeitlimit überschritten" : "S3-Bucket nicht erreichbar oder Zugriff verweigert",
})
} finally {
clearTimeout(timeout)
@@ -116,7 +113,6 @@ export const buildSystemStatus = async (server: FastifyInstance) => {
const uname = nodeMetrics?.get("node_uname_info")?.[0]?.labels || null
const databaseCheck = await server.db.execute("SELECT NOW() as now")
const minioUrl = s3EndpointUrl()
return {
checkedAt: checkedAt.toISOString(),
@@ -160,9 +156,8 @@ export const buildSystemStatus = async (server: FastifyInstance) => {
url: nodeExporterMetricsUrl,
error: nodeExporterError,
}),
minio: minioUrl ? await checkHttp(`${minioUrl}/minio/health/live`) : serviceState(false, {
error: "S3_ENDPOINT ist nicht gesetzt",
}),
// Preserve the response key for older clients; check the authenticated S3 API for every provider.
minio: await checkFileStorage(),
},
}
}