()
| 1240 | * never query text or row data — so this stays safe to share. |
| 1241 | */ |
| 1242 | async function getPostgresClusterHealth(): Promise<JSONObject> { |
| 1243 | const result: JSONObject = { |
| 1244 | connected: false, |
| 1245 | clusterName: null, |
| 1246 | serverVersion: null, |
| 1247 | isInRecovery: false, |
| 1248 | role: null, |
| 1249 | uptimeSeconds: null, |
| 1250 | replication: [], |
| 1251 | replicationSlots: [], |
| 1252 | connections: null, |
| 1253 | database: null, |
| 1254 | wraparound: null, |
| 1255 | topTablesByDeadTuples: [], |
| 1256 | databaseSizeInBytes: null, |
| 1257 | }; |
| 1258 | |
| 1259 | try { |
| 1260 | const dataSource: ReturnType<typeof PostgresAppInstance.getDataSource> = |
| 1261 | PostgresAppInstance.getDataSource(); |
| 1262 | |
| 1263 | if (!dataSource) { |
| 1264 | return result; |
| 1265 | } |
| 1266 | |
| 1267 | result["connected"] = true; |
| 1268 | |
| 1269 | // 1. Node identity & role — is this the primary or a standby, and for how long. |
| 1270 | try { |
| 1271 | const identityRows: Array<{ |
| 1272 | cluster_name: string | null; |
| 1273 | server_version: string | null; |
| 1274 | in_recovery: boolean; |
| 1275 | uptime_seconds: string | null; |
| 1276 | }> = await dataSource.query( |
| 1277 | `SELECT |
| 1278 | current_setting('cluster_name', true) AS cluster_name, |
| 1279 | current_setting('server_version') AS server_version, |
| 1280 | pg_is_in_recovery() AS in_recovery, |
| 1281 | ROUND(EXTRACT(EPOCH FROM (now() - pg_postmaster_start_time()))) AS uptime_seconds`, |
| 1282 | ); |
| 1283 | |
| 1284 | const identity: (typeof identityRows)[number] | undefined = |
| 1285 | identityRows?.[0]; |
| 1286 | |
| 1287 | if (identity) { |
| 1288 | result["clusterName"] = identity.cluster_name || null; |
| 1289 | result["serverVersion"] = identity.server_version || null; |
| 1290 | result["isInRecovery"] = Boolean(identity.in_recovery); |
| 1291 | result["role"] = identity.in_recovery ? "standby" : "primary"; |
| 1292 | result["uptimeSeconds"] = toNumberOrNull(identity.uptime_seconds); |
| 1293 | } |
| 1294 | } catch (err) { |
| 1295 | logger.debug("AdminHealth: postgres identity probe failed"); |
| 1296 | logger.debug(err); |
| 1297 | } |
| 1298 | |
| 1299 | // 2. Streaming replication — the primary's view of every connected standby. |
no test coverage detected