@indiekitai/pg-dash 0.4.5 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.js CHANGED
@@ -522,30 +522,44 @@ SHOW shared_buffers;`,
522
522
  }
523
523
  try {
524
524
  const r = await client.query(`
525
- SELECT pid, state, now() - state_change AS idle_duration,
525
+ SELECT pid,
526
526
  client_addr::text, application_name,
527
527
  extract(epoch from now() - state_change)::int AS idle_seconds
528
528
  FROM pg_stat_activity
529
- WHERE state IN ('idle', 'idle in transaction')
529
+ WHERE state = 'idle in transaction'
530
530
  AND now() - state_change > $1 * interval '1 minute'
531
531
  AND pid != pg_backend_pid()
532
+ ORDER BY idle_seconds DESC
532
533
  `, [longQueryThreshold2]);
533
- for (const row of r.rows) {
534
- const isIdleTx = row.state === "idle in transaction";
534
+ if (r.rows.length === 1) {
535
+ const row = r.rows[0];
535
536
  issues.push({
536
- id: `maint-idle-${row.pid}`,
537
- severity: isIdleTx ? "warning" : "info",
537
+ id: `maint-idle-tx-${row.pid}`,
538
+ severity: "warning",
538
539
  category: "maintenance",
539
- title: `${isIdleTx ? "Idle in transaction" : "Idle connection"} (PID ${row.pid})`,
540
- description: `PID ${row.pid} from ${row.client_addr || "local"} (${row.application_name || "unknown"}) has been ${row.state} for ${Math.round(row.idle_seconds / 60)} minutes.`,
540
+ title: `Idle-in-transaction connection (PID ${row.pid})`,
541
+ description: `PID ${row.pid} from ${row.client_addr || "local"} (${row.application_name || "unknown"}) has been idle in transaction for ${Math.round(row.idle_seconds / 60)} minutes. This holds locks and blocks VACUUM.`,
541
542
  fix: `SELECT pg_terminate_backend(${row.pid});`,
542
- impact: isIdleTx ? "Idle-in-transaction connections hold locks and prevent VACUUM." : "Idle connections consume connection slots.",
543
+ impact: "Idle-in-transaction connections hold locks and prevent VACUUM.",
544
+ effort: "quick"
545
+ });
546
+ } else if (r.rows.length > 1) {
547
+ const pids = r.rows.map((row) => row.pid);
548
+ const maxMin = Math.round(r.rows[0].idle_seconds / 60);
549
+ issues.push({
550
+ id: `maint-idle-tx-multi`,
551
+ severity: "warning",
552
+ category: "maintenance",
553
+ title: `${r.rows.length} idle-in-transaction connections (longest: ${maxMin}m)`,
554
+ description: `${r.rows.length} connections have been idle in transaction for over ${longQueryThreshold2} minutes. These hold locks and prevent VACUUM from running.`,
555
+ fix: `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' AND now() - state_change > interval '${longQueryThreshold2} minutes';`,
556
+ impact: "Idle-in-transaction connections hold locks and prevent VACUUM.",
543
557
  effort: "quick"
544
558
  });
545
559
  }
546
560
  } catch (err) {
547
- console.error("[advisor] Error checking idle connections:", err.message);
548
- skipped.push("idle connections: " + err.message);
561
+ console.error("[advisor] Error checking idle-in-transaction connections:", err.message);
562
+ skipped.push("idle-in-transaction: " + err.message);
549
563
  }
550
564
  try {
551
565
  const r = await client.query(`