-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdb.ts
More file actions
96 lines (80 loc) · 2.76 KB
/
db.ts
File metadata and controls
96 lines (80 loc) · 2.76 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
import { PrismaClient } from "@prisma/client";
const prismaClientSingleton = () => {
return new PrismaClient();
};
declare const globalThis: {
prismaGlobal: ReturnType<typeof prismaClientSingleton>;
} & typeof global;
// Cache database availability check to avoid repeated connection attempts
let dbAvailabilityCache: { available: boolean; lastChecked: number } | null =
null;
const DB_CHECK_CACHE_DURATION = 30000; // 30 seconds
// Clear the database availability cache (useful for testing or manual refresh)
export const clearDatabaseAvailabilityCache = (): void => {
dbAvailabilityCache = null;
};
// Check if DATABASE_URL is available and database is reachable
export const isDatabaseAvailable = async (): Promise<boolean> => {
// First check if DATABASE_URL is set
if (!process.env.DATABASE_URL) {
return false;
}
// Check cache first
const now = Date.now();
if (
dbAvailabilityCache &&
now - dbAvailabilityCache.lastChecked < DB_CHECK_CACHE_DURATION
) {
return dbAvailabilityCache.available;
}
try {
// Attempt to connect and perform a simple query
// Use a temporary PrismaClient instance for the availability check
const tempPrisma = new PrismaClient();
await tempPrisma.$queryRaw`SELECT 1`;
await tempPrisma.$disconnect();
// Cache successful result
dbAvailabilityCache = { available: true, lastChecked: now };
return true;
} catch (error) {
console.error(
"Database connectivity check failed:",
error instanceof Error ? error.message : JSON.stringify(error)
);
// Cache failed result for a shorter duration to allow retries
dbAvailabilityCache = {
available: false,
lastChecked: now - (DB_CHECK_CACHE_DURATION - 5000),
};
return false;
}
};
// Safe database operation wrapper
export const safeDbOperation = async <T>(
operation: () => Promise<T>,
fallback: T
): Promise<{ data: T; error: string | null }> => {
const dbAvailable = await isDatabaseAvailable();
if (!dbAvailable) {
const errorMessage = !process.env.DATABASE_URL
? "Database connection not configured. Please set DATABASE_URL environment variable."
: "Database is not reachable. Please check your database connection and ensure the database server is running.";
return {
data: fallback,
error: errorMessage,
};
}
try {
const data = await operation();
return { data, error: null };
} catch (error) {
console.error("Database operation failed:", error);
return {
data: fallback,
error: error instanceof Error ? error.message : "Unknown database error",
};
}
};
const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();
export default prisma;
if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma;