UNPKG

@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
/* 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