postgresai 0.14.0-dev.80 → 0.14.0-dev.81

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.
@@ -13064,7 +13064,7 @@ var {
13064
13064
  // package.json
13065
13065
  var package_default = {
13066
13066
  name: "postgresai",
13067
- version: "0.14.0-dev.80",
13067
+ version: "0.14.0-dev.81",
13068
13068
  description: "postgres_ai CLI",
13069
13069
  license: "Apache-2.0",
13070
13070
  private: false,
@@ -15889,7 +15889,7 @@ var Result = import_lib.default.Result;
15889
15889
  var TypeOverrides = import_lib.default.TypeOverrides;
15890
15890
  var defaults = import_lib.default.defaults;
15891
15891
  // package.json
15892
- var version = "0.14.0-dev.80";
15892
+ var version = "0.14.0-dev.81";
15893
15893
  var package_default2 = {
15894
15894
  name: "postgresai",
15895
15895
  version,
@@ -27872,6 +27872,64 @@ async function generateG001(client, nodeName) {
27872
27872
  };
27873
27873
  return report;
27874
27874
  }
27875
+ async function generateG003(client, nodeName) {
27876
+ const report = createBaseReport("G003", "Timeouts, locks, deadlocks", nodeName);
27877
+ const postgresVersion = await getPostgresVersion(client);
27878
+ const pgMajorVersion = parseInt(postgresVersion.server_major_ver, 10) || 16;
27879
+ const allSettings = await getSettings(client, pgMajorVersion);
27880
+ const lockTimeoutSettingNames = [
27881
+ "lock_timeout",
27882
+ "statement_timeout",
27883
+ "idle_in_transaction_session_timeout",
27884
+ "idle_session_timeout",
27885
+ "deadlock_timeout",
27886
+ "max_locks_per_transaction",
27887
+ "max_pred_locks_per_transaction",
27888
+ "max_pred_locks_per_relation",
27889
+ "max_pred_locks_per_page",
27890
+ "log_lock_waits",
27891
+ "transaction_timeout"
27892
+ ];
27893
+ const lockSettings = {};
27894
+ for (const name of lockTimeoutSettingNames) {
27895
+ if (allSettings[name]) {
27896
+ lockSettings[name] = allSettings[name];
27897
+ }
27898
+ }
27899
+ let deadlockStats = null;
27900
+ let deadlockError = null;
27901
+ try {
27902
+ const statsResult = await client.query(`
27903
+ select
27904
+ coalesce(sum(deadlocks), 0)::bigint as deadlocks,
27905
+ coalesce(sum(conflicts), 0)::bigint as conflicts,
27906
+ min(stats_reset)::text as stats_reset
27907
+ from pg_stat_database
27908
+ where datname = current_database()
27909
+ `);
27910
+ if (statsResult.rows.length > 0) {
27911
+ const row = statsResult.rows[0];
27912
+ deadlockStats = {
27913
+ deadlocks: parseInt(row.deadlocks, 10),
27914
+ conflicts: parseInt(row.conflicts, 10),
27915
+ stats_reset: row.stats_reset || null
27916
+ };
27917
+ }
27918
+ } catch (err) {
27919
+ const errorMsg = err instanceof Error ? err.message : String(err);
27920
+ console.log(`[G003] Error querying deadlock stats: ${errorMsg}`);
27921
+ deadlockError = errorMsg;
27922
+ }
27923
+ report.results[nodeName] = {
27924
+ data: {
27925
+ settings: lockSettings,
27926
+ deadlock_stats: deadlockStats,
27927
+ ...deadlockError && { deadlock_stats_error: deadlockError }
27928
+ },
27929
+ postgres_version: postgresVersion
27930
+ };
27931
+ return report;
27932
+ }
27875
27933
  var REPORT_GENERATORS = {
27876
27934
  A002: generateA002,
27877
27935
  A003: generateA003,
@@ -27882,6 +27940,7 @@ var REPORT_GENERATORS = {
27882
27940
  D004: generateD004,
27883
27941
  F001: generateF001,
27884
27942
  G001: generateG001,
27943
+ G003: generateG003,
27885
27944
  H001: generateH001,
27886
27945
  H002: generateH002,
27887
27946
  H004: generateH004
package/lib/checkup.ts CHANGED
@@ -1358,6 +1358,82 @@ async function generateG001(client: Client, nodeName: string): Promise<Report> {
1358
1358
  return report;
1359
1359
  }
1360
1360
 
1361
+ /**
1362
+ * Generate G003 report - Timeouts, locks, deadlocks
1363
+ *
1364
+ * Collects timeout and lock-related settings, plus deadlock statistics.
1365
+ */
1366
+ async function generateG003(client: Client, nodeName: string): Promise<Report> {
1367
+ const report = createBaseReport("G003", "Timeouts, locks, deadlocks", nodeName);
1368
+ const postgresVersion = await getPostgresVersion(client);
1369
+ const pgMajorVersion = parseInt(postgresVersion.server_major_ver, 10) || 16;
1370
+ const allSettings = await getSettings(client, pgMajorVersion);
1371
+
1372
+ // Timeout and lock-related setting names
1373
+ const lockTimeoutSettingNames = [
1374
+ "lock_timeout",
1375
+ "statement_timeout",
1376
+ "idle_in_transaction_session_timeout",
1377
+ "idle_session_timeout",
1378
+ "deadlock_timeout",
1379
+ "max_locks_per_transaction",
1380
+ "max_pred_locks_per_transaction",
1381
+ "max_pred_locks_per_relation",
1382
+ "max_pred_locks_per_page",
1383
+ "log_lock_waits",
1384
+ "transaction_timeout",
1385
+ ];
1386
+
1387
+ const lockSettings: Record<string, SettingInfo> = {};
1388
+ for (const name of lockTimeoutSettingNames) {
1389
+ if (allSettings[name]) {
1390
+ lockSettings[name] = allSettings[name];
1391
+ }
1392
+ }
1393
+
1394
+ // Get deadlock statistics from pg_stat_database
1395
+ let deadlockStats: {
1396
+ deadlocks: number;
1397
+ conflicts: number;
1398
+ stats_reset: string | null;
1399
+ } | null = null;
1400
+ let deadlockError: string | null = null;
1401
+
1402
+ try {
1403
+ const statsResult = await client.query(`
1404
+ select
1405
+ coalesce(sum(deadlocks), 0)::bigint as deadlocks,
1406
+ coalesce(sum(conflicts), 0)::bigint as conflicts,
1407
+ min(stats_reset)::text as stats_reset
1408
+ from pg_stat_database
1409
+ where datname = current_database()
1410
+ `);
1411
+ if (statsResult.rows.length > 0) {
1412
+ const row = statsResult.rows[0];
1413
+ deadlockStats = {
1414
+ deadlocks: parseInt(row.deadlocks, 10),
1415
+ conflicts: parseInt(row.conflicts, 10),
1416
+ stats_reset: row.stats_reset || null,
1417
+ };
1418
+ }
1419
+ } catch (err) {
1420
+ const errorMsg = err instanceof Error ? err.message : String(err);
1421
+ console.log(`[G003] Error querying deadlock stats: ${errorMsg}`);
1422
+ deadlockError = errorMsg;
1423
+ }
1424
+
1425
+ report.results[nodeName] = {
1426
+ data: {
1427
+ settings: lockSettings,
1428
+ deadlock_stats: deadlockStats,
1429
+ ...(deadlockError && { deadlock_stats_error: deadlockError }),
1430
+ },
1431
+ postgres_version: postgresVersion,
1432
+ };
1433
+
1434
+ return report;
1435
+ }
1436
+
1361
1437
  /**
1362
1438
  * Available report generators
1363
1439
  */
@@ -1371,6 +1447,7 @@ export const REPORT_GENERATORS: Record<string, (client: Client, nodeName: string
1371
1447
  D004: generateD004,
1372
1448
  F001: generateF001,
1373
1449
  G001: generateG001,
1450
+ G003: generateG003,
1374
1451
  H001: generateH001,
1375
1452
  H002: generateH002,
1376
1453
  H004: generateH004,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postgresai",
3
- "version": "0.14.0-dev.80",
3
+ "version": "0.14.0-dev.81",
4
4
  "description": "postgres_ai CLI",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,
@@ -86,7 +86,7 @@ describe("createBaseReport", () => {
86
86
  // Tests for CHECK_INFO
87
87
  describe("CHECK_INFO and REPORT_GENERATORS", () => {
88
88
  // Express-mode checks that have generators
89
- const expressCheckIds = ["A002", "A003", "A004", "A007", "A013", "D001", "D004", "F001", "G001", "H001", "H002", "H004"];
89
+ const expressCheckIds = ["A002", "A003", "A004", "A007", "A013", "D001", "D004", "F001", "G001", "G003", "H001", "H002", "H004"];
90
90
 
91
91
  test("CHECK_INFO contains all express-mode checks", () => {
92
92
  for (const checkId of expressCheckIds) {