Swadhin Biswas Feature/ai code reviewer (#80) · 8/17/2026
9740d3d
121 lines · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { getDatabase } from "@/db";
import { sql } from "drizzle-orm";
import type { APIRoute } from "astro";
import { withErrorHandler } from "@/lib/errors";
import { isDistributedLocking } from "@/lib/distributed-lock";
import { isDistributed as isDistributedRateLimit } from "@/lib/rate-limit";
import { getQueueWorkerScalingReadiness } from "@/lib/queue-worker";

export const GET: APIRoute = withErrorHandler(async () => {
  const checks: Record<
    string,
    { status: "ok" | "error"; message?: string; latency?: number; details?: unknown }
  > = {};

  // Check database
  const dbStart = Date.now();
  try {
    const db = getDatabase() as any;
    if (db.execute) {
      await db.execute(sql`SELECT 1`);
    } else {
      await db.run(sql`SELECT 1`);
    }
    checks.database = { status: "ok", latency: Date.now() - dbStart };
  } catch (error) {
    checks.database = {
      status: "error",
      message: error instanceof Error ? error.message : "Unknown error",
    };
  }

  // Check Redis (if configured)
  if (process.env.REDIS_URL) {
    const redisStart = Date.now();
    try {
      const { redis } = await import("@/lib/redis");
      const pong = await redis.ping();
      if (pong === "PONG" || pong === "OK") {
        checks.redis = { status: "ok", latency: Date.now() - redisStart };
      } else {
        checks.redis = { status: "error", message: `Unexpected ping response: ${pong}` };
      }
    } catch (error) {
      checks.redis = {
        status: "error",
        message: error instanceof Error ? error.message : "Unknown error",
      };
    }
  }

  // Check storage
  try {
    const fs = await import("fs/promises");
    const storagePath = process.env.STORAGE_PATH || "./data/storage";
    await fs.mkdir(storagePath, { recursive: true }).catch(() => {});
    await fs.access(storagePath);
    checks.storage = { status: "ok" };
  } catch (error) {
    checks.storage = {
      status: "error",
      message:
        error instanceof Error ? error.message : "Storage not accessible",
    };
  }

  // Check horizontal scaling readiness for self-hosted deployments
  const queueWorker = getQueueWorkerScalingReadiness();
  const redisConfigured = Boolean(process.env.REDIS_URL?.trim());
  const production = process.env.NODE_ENV === "production";
  const scalingIssues: string[] = [];

  if (production && process.env.SKIP_REDIS_CHECK !== "1") {
    if (!redisConfigured) {
      scalingIssues.push("REDIS_URL is required in production for distributed coordination");
    }
    if (!isDistributedLocking) {
      scalingIssues.push("Distributed locking is not active");
    }
    if (!isDistributedRateLimit) {
      scalingIssues.push("Distributed rate limiting is not active");
    }
    if (!queueWorker.multiInstanceSafe) {
      scalingIssues.push("Queue worker is not multi-instance safe");
    }
  }

  checks.scaling = {
    status: scalingIssues.length ? "error" : "ok",
    ...(scalingIssues.length ? { message: scalingIssues.join("; ") } : {}),
    details: {
      production,
      redisConfigured,
      distributedLocking: isDistributedLocking,
      distributedRateLimit: isDistributedRateLimit,
      queueWorker,
    },
  };

  // Overall health
  const isHealthy = Object.values(checks).every(
    (check) => check.status === "ok"
  );

  return new Response(
    JSON.stringify({
      status: isHealthy ? "healthy" : "unhealthy",
      timestamp: new Date(),
      version: process.env.npm_package_version || "1.0.0",
      uptime: process.uptime(),
      checks,
    }),
    {
      status: isHealthy ? 200 : 503,
      headers: {
        "Content-Type": "application/json",
        "Cache-Control": "no-store, no-cache, must-revalidate",
      },
    }
  );
});