@settlemint/sdk-hasura
Version:
Hasura and PostgreSQL integration module for SettleMint SDK, enabling database operations and GraphQL queries
105 lines (103 loc) • 3.2 kB
JavaScript
/* SettleMint Postgres SDK - Database Utils */
import { runsOnServer } from "@settlemint/sdk-utils/runtime";
import pg from "pg";
//#region src/postgres.ts
/**
* Utility function to pause execution for a specified duration
*
* @param ms - The number of milliseconds to sleep
* @returns A promise that resolves after the specified duration
*/
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
/**
* Configures error handling and recovery mechanisms for a PostgreSQL connection pool
*
* @param pool - The PostgreSQL connection pool to configure
*/
function setupErrorHandling(pool) {
let retryCount = 0;
let isRetrying = false;
const clientErrorHandlers = new WeakSet();
const handlePoolError = async (err) => {
console.error("[Drizzle] Pool error occurred:", err);
if (isRetrying) {
console.log("[Drizzle] Recovery already in progress, skipping");
return;
}
if (retryCount < 3) {
isRetrying = true;
retryCount++;
console.log(`[Drizzle] Attempting to recover - retry ${retryCount}/3`);
try {
const client = await pool.connect();
try {
await Promise.race([client.query("SELECT 1"), new Promise((_, reject) => setTimeout(() => reject(new Error("Query timeout")), 5e3))]);
console.log("[Drizzle] Successfully recovered connection");
retryCount = 0;
} finally {
client.release();
}
} catch (retryError) {
console.error(`[Drizzle] Recovery attempt ${retryCount} failed:`, retryError);
await sleep(5e3 * 2 ** (retryCount - 1));
} finally {
isRetrying = false;
}
} else {
console.error("[Drizzle] Max retries exceeded - pool is in an error state");
pool.emit("permanent-failure", err);
}
};
const handleConnect = (client) => {
if (!clientErrorHandlers.has(client)) {
clientErrorHandlers.add(client);
client.on("error", (err) => {
console.error("[Drizzle] Database client error:", err);
});
}
retryCount = 0;
isRetrying = false;
};
pool.on("error", handlePoolError);
pool.on("connect", handleConnect);
}
/**
* Creates a PostgreSQL connection pool with error handling and retry mechanisms
*
* @param databaseUrl - The PostgreSQL connection URL
* @returns A configured PostgreSQL connection pool
* @throws Will throw an error if called from browser runtime
* @example
* import { createPostgresPool } from '@settlemint/sdk-hasura';
*
* const pool = createPostgresPool(process.env.SETTLEMINT_HASURA_DATABASE_URL);
*
* // The pool will automatically handle connection errors and retries
* const client = await pool.connect();
* try {
* const result = await client.query('SELECT NOW()');
* console.log(result.rows[0]);
* } finally {
* client.release();
* }
*/
function createPostgresPool(databaseUrl) {
if (!databaseUrl?.trim()) {
throw new Error("Database URL is required");
}
if (!runsOnServer) {
throw new Error("Drizzle client can only be created on the server side");
}
const pool = new pg.Pool({
connectionString: databaseUrl,
max: 10,
idleTimeoutMillis: 3e4,
connectionTimeoutMillis: 5e3,
maxLifetimeSeconds: 0
});
setupErrorHandling(pool);
return pool;
}
//#endregion
export { createPostgresPool };
//# sourceMappingURL=postgres.js.map