diff --git a/src/server/routes/system/health.ts b/src/server/routes/system/health.ts index 23672c92f..f358ad845 100644 --- a/src/server/routes/system/health.ts +++ b/src/server/routes/system/health.ts @@ -5,7 +5,6 @@ import { isDatabaseReachable } from "../../../shared/db/client"; import { env } from "../../../shared/utils/env"; import { isRedisReachable } from "../../../shared/utils/redis/redis"; import { thirdwebClientId } from "../../../shared/utils/sdk"; -import { createCustomError } from "../../middleware/error"; type EngineFeature = | "KEYPAIR_AUTH" @@ -14,8 +13,10 @@ type EngineFeature = | "HETEROGENEOUS_WALLET_TYPES" | "SMART_BACKEND_WALLETS"; -const ReplySchemaOk = Type.Object({ - status: Type.String(), +const ReplySchema = Type.Object({ + db: Type.Boolean(), + redis: Type.Boolean(), + auth: Type.Boolean(), engineVersion: Type.Optional(Type.String()), engineTier: Type.Optional(Type.String()), features: Type.Array( @@ -30,15 +31,9 @@ const ReplySchemaOk = Type.Object({ clientId: Type.String(), }); -const ReplySchemaError = Type.Object({ - error: Type.String(), -}); - -const responseBodySchema = Type.Union([ReplySchemaOk, ReplySchemaError]); - export async function healthCheck(fastify: FastifyInstance) { fastify.route<{ - Reply: Static; + Reply: Static; }>({ method: "GET", url: "/system/health", @@ -49,34 +44,27 @@ export async function healthCheck(fastify: FastifyInstance) { tags: ["System"], operationId: "checkHealth", response: { - [StatusCodes.OK]: ReplySchemaOk, - [StatusCodes.SERVICE_UNAVAILABLE]: ReplySchemaError, + [StatusCodes.OK]: ReplySchema, + [StatusCodes.SERVICE_UNAVAILABLE]: ReplySchema, }, }, handler: async (_, res) => { - if (!(await isDatabaseReachable())) { - throw createCustomError( - "The database is unreachable.", - StatusCodes.SERVICE_UNAVAILABLE, - "FAILED_HEALTHCHECK", - ); - } - - if (!(await isRedisReachable())) { - throw createCustomError( - "Redis is unreachable.", - StatusCodes.SERVICE_UNAVAILABLE, - "FAILED_HEALTHCHECK", - ); - } + const db = await isDatabaseReachable(); + const redis = await isRedisReachable(); + const auth = await isAuthValid(); + const isHealthy = db && redis && auth; - res.status(StatusCodes.OK).send({ - status: "OK", - engineVersion: env.ENGINE_VERSION, - engineTier: env.ENGINE_TIER ?? "SELF_HOSTED", - features: getFeatures(), - clientId: thirdwebClientId, - }); + res + .status(isHealthy ? StatusCodes.OK : StatusCodes.SERVICE_UNAVAILABLE) + .send({ + db, + redis, + auth, + engineVersion: env.ENGINE_VERSION, + engineTier: env.ENGINE_TIER ?? "SELF_HOSTED", + features: getFeatures(), + clientId: thirdwebClientId, + }); }, }); } @@ -95,3 +83,16 @@ const getFeatures = (): EngineFeature[] => { return features; }; + +async function isAuthValid() { + try { + const resp = await fetch("https://api.thirdweb.com/v2/keys/use", { + headers: { + "x-secret-key": env.THIRDWEB_API_SECRET_KEY, + }, + }); + return resp.ok; + } catch { + return false; + } +}