@venturekit/data 0.0.0-dev.20260505153744 → 0.0.0-dev.20260505164727
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/internal/logger.d.ts +28 -0
- package/dist/internal/logger.d.ts.map +1 -0
- package/dist/internal/logger.js +62 -0
- package/dist/internal/logger.js.map +1 -0
- package/dist/query/index.d.ts +8 -0
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/index.js +61 -1
- package/dist/query/index.js.map +1 -1
- package/dist/query/pool.d.ts +15 -0
- package/dist/query/pool.d.ts.map +1 -1
- package/dist/query/pool.js +60 -5
- package/dist/query/pool.js.map +1 -1
- package/dist/query/secret.d.ts +17 -0
- package/dist/query/secret.d.ts.map +1 -1
- package/dist/query/secret.js +97 -1
- package/dist/query/secret.js.map +1 -1
- package/dist/query/transaction.d.ts.map +1 -1
- package/dist/query/transaction.js +54 -2
- package/dist/query/transaction.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny structured logger for `@venturekit/data`.
|
|
3
|
+
*
|
|
4
|
+
* The runtime package wires a pino logger keyed by `requestId`, but
|
|
5
|
+
* `@venturekit/data` is consumed from CLI tooling, queue handlers, and
|
|
6
|
+
* background workers too — none of which can rely on a pino instance
|
|
7
|
+
* being injected. Emitting JSON straight to stdout in the same shape
|
|
8
|
+
* pino uses keeps CloudWatch Logs Insights queries (`fields @timestamp,
|
|
9
|
+
* level, msg, durationMs`) consistent across runtime + data lines, and
|
|
10
|
+
* stays a no-op outside Lambda where stdout still routes somewhere
|
|
11
|
+
* sensible.
|
|
12
|
+
*
|
|
13
|
+
* Filtering is driven by `DB_LOG_LEVEL` (`info` | `warn` | `error`).
|
|
14
|
+
* Default `info`. `error` is the floor — we never silence error lines
|
|
15
|
+
* because they're the ones operators need when diagnosing production
|
|
16
|
+
* incidents.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Internal logger for the data package. Exposed via the package barrel
|
|
20
|
+
* so user code can opt into the same emission format if it wants to;
|
|
21
|
+
* not part of the documented surface yet.
|
|
22
|
+
*/
|
|
23
|
+
export declare const dbLog: {
|
|
24
|
+
info(msg: string, fields?: Record<string, unknown>): void;
|
|
25
|
+
warn(msg: string, fields?: Record<string, unknown>): void;
|
|
26
|
+
error(msg: string, fields?: Record<string, unknown>): void;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/internal/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAiCH;;;;GAIG;AACH,eAAO,MAAM,KAAK;cACN,MAAM,WAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAQ,IAAI;cAGnD,MAAM,WAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAQ,IAAI;eAGlD,MAAM,WAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAQ,IAAI;CAG/D,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny structured logger for `@venturekit/data`.
|
|
3
|
+
*
|
|
4
|
+
* The runtime package wires a pino logger keyed by `requestId`, but
|
|
5
|
+
* `@venturekit/data` is consumed from CLI tooling, queue handlers, and
|
|
6
|
+
* background workers too — none of which can rely on a pino instance
|
|
7
|
+
* being injected. Emitting JSON straight to stdout in the same shape
|
|
8
|
+
* pino uses keeps CloudWatch Logs Insights queries (`fields @timestamp,
|
|
9
|
+
* level, msg, durationMs`) consistent across runtime + data lines, and
|
|
10
|
+
* stays a no-op outside Lambda where stdout still routes somewhere
|
|
11
|
+
* sensible.
|
|
12
|
+
*
|
|
13
|
+
* Filtering is driven by `DB_LOG_LEVEL` (`info` | `warn` | `error`).
|
|
14
|
+
* Default `info`. `error` is the floor — we never silence error lines
|
|
15
|
+
* because they're the ones operators need when diagnosing production
|
|
16
|
+
* incidents.
|
|
17
|
+
*/
|
|
18
|
+
const LEVEL_PRIORITY = {
|
|
19
|
+
info: 1,
|
|
20
|
+
warn: 2,
|
|
21
|
+
error: 3,
|
|
22
|
+
};
|
|
23
|
+
function envLevel() {
|
|
24
|
+
const raw = (process.env.DB_LOG_LEVEL ?? 'info').toLowerCase();
|
|
25
|
+
if (raw === 'warn' || raw === 'error')
|
|
26
|
+
return raw;
|
|
27
|
+
return 'info';
|
|
28
|
+
}
|
|
29
|
+
function emit(level, msg, fields) {
|
|
30
|
+
if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[envLevel()])
|
|
31
|
+
return;
|
|
32
|
+
const entry = {
|
|
33
|
+
level,
|
|
34
|
+
time: new Date().toISOString(),
|
|
35
|
+
component: '@venturekit/data',
|
|
36
|
+
...fields,
|
|
37
|
+
msg,
|
|
38
|
+
};
|
|
39
|
+
// stdout matches pino's default and is captured by Lambda alongside
|
|
40
|
+
// stderr. Using stdout (not stderr) keeps the log line ordered with
|
|
41
|
+
// the runtime's `Request started` / `Request completed` lines emitted
|
|
42
|
+
// by pino in `@venturekit/runtime`.
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.log(JSON.stringify(entry));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Internal logger for the data package. Exposed via the package barrel
|
|
48
|
+
* so user code can opt into the same emission format if it wants to;
|
|
49
|
+
* not part of the documented surface yet.
|
|
50
|
+
*/
|
|
51
|
+
export const dbLog = {
|
|
52
|
+
info(msg, fields = {}) {
|
|
53
|
+
emit('info', msg, fields);
|
|
54
|
+
},
|
|
55
|
+
warn(msg, fields = {}) {
|
|
56
|
+
emit('warn', msg, fields);
|
|
57
|
+
},
|
|
58
|
+
error(msg, fields = {}) {
|
|
59
|
+
emit('error', msg, fields);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/internal/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,cAAc,GAA0B;IAC5C,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,SAAS,QAAQ;IACf,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/D,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC;IAClD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,IAAI,CAAC,KAAY,EAAE,GAAW,EAAE,MAA+B;IACtE,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;QAAE,OAAO;IAC/D,MAAM,KAAK,GAA4B;QACrC,KAAK;QACL,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC9B,SAAS,EAAE,kBAAkB;QAC7B,GAAG,MAAM;QACT,GAAG;KACJ,CAAC;IACF,oEAAoE;IACpE,oEAAoE;IACpE,sEAAsE;IACtE,oCAAoC;IACpC,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,IAAI,CAAC,GAAW,EAAE,SAAkC,EAAE;QACpD,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC,GAAW,EAAE,SAAkC,EAAE;QACpD,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,KAAK,CAAC,GAAW,EAAE,SAAkC,EAAE;QACrD,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC;CACF,CAAC"}
|
package/dist/query/index.d.ts
CHANGED
|
@@ -46,6 +46,14 @@
|
|
|
46
46
|
*/
|
|
47
47
|
import { type MapperOptions } from './mapper.js';
|
|
48
48
|
import type { ResultsMapper } from './transaction.js';
|
|
49
|
+
/**
|
|
50
|
+
* Default threshold above which a successful query is logged as slow.
|
|
51
|
+
* Tuned for OLTP workloads (reads in single-digit ms, writes 10–50 ms);
|
|
52
|
+
* 1 s catches obvious offenders without spamming the log on warm cold-
|
|
53
|
+
* start variations or transient RDS read replica blips. Override per
|
|
54
|
+
* environment via `DB_SLOW_QUERY_THRESHOLD_MS`. Set to `0` to disable.
|
|
55
|
+
*/
|
|
56
|
+
export declare const DEFAULT_SLOW_QUERY_THRESHOLD_MS = 1000;
|
|
49
57
|
export { getPool, applyDatabaseUrlToEnv } from './pool.js';
|
|
50
58
|
export { applyDbSecretToEnv } from './secret.js';
|
|
51
59
|
export { mapResults, mapRow, configureMapper, getMapperConfig, } from './mapper.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/query/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAIH,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/query/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAIH,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAItD;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,OAAQ,CAAC;AAqBrD,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,UAAU,EACV,MAAM,EACN,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACvD,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,EAAE,EACvB,aAAa,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EAChC,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,CAAC,CAAC,CA6CZ"}
|
package/dist/query/index.js
CHANGED
|
@@ -47,6 +47,33 @@
|
|
|
47
47
|
import { getPool } from './pool.js';
|
|
48
48
|
import { mapResults } from './mapper.js';
|
|
49
49
|
import { applyDbSecretToEnv } from './secret.js';
|
|
50
|
+
import { dbLog } from '../internal/logger.js';
|
|
51
|
+
/**
|
|
52
|
+
* Default threshold above which a successful query is logged as slow.
|
|
53
|
+
* Tuned for OLTP workloads (reads in single-digit ms, writes 10–50 ms);
|
|
54
|
+
* 1 s catches obvious offenders without spamming the log on warm cold-
|
|
55
|
+
* start variations or transient RDS read replica blips. Override per
|
|
56
|
+
* environment via `DB_SLOW_QUERY_THRESHOLD_MS`. Set to `0` to disable.
|
|
57
|
+
*/
|
|
58
|
+
export const DEFAULT_SLOW_QUERY_THRESHOLD_MS = 1_000;
|
|
59
|
+
function resolveSlowQueryThresholdMs() {
|
|
60
|
+
const raw = process.env.DB_SLOW_QUERY_THRESHOLD_MS;
|
|
61
|
+
if (!raw)
|
|
62
|
+
return DEFAULT_SLOW_QUERY_THRESHOLD_MS;
|
|
63
|
+
const n = Number.parseInt(raw, 10);
|
|
64
|
+
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_SLOW_QUERY_THRESHOLD_MS;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Build a short, single-line preview of a SQL string for log fields.
|
|
68
|
+
* Collapses runs of whitespace and clips to 120 chars so log lines
|
|
69
|
+
* stay grep-friendly. Parameter values are never included — the
|
|
70
|
+
* `$1`, `$2` placeholders are passed through verbatim, so PII never
|
|
71
|
+
* leaks into CloudWatch.
|
|
72
|
+
*/
|
|
73
|
+
function previewSql(sql) {
|
|
74
|
+
const single = sql.replace(/\s+/g, ' ').trim();
|
|
75
|
+
return single.length > 120 ? `${single.slice(0, 117)}...` : single;
|
|
76
|
+
}
|
|
50
77
|
export { getPool, applyDatabaseUrlToEnv } from './pool.js';
|
|
51
78
|
export { applyDbSecretToEnv } from './secret.js';
|
|
52
79
|
export { mapResults, mapRow, configureMapper, getMapperConfig, } from './mapper.js';
|
|
@@ -92,7 +119,40 @@ export async function query(sqlQuery, queryParams, resultsMapper, mapperOptions)
|
|
|
92
119
|
// so concurrent first calls share one fetch.
|
|
93
120
|
await applyDbSecretToEnv();
|
|
94
121
|
const pool = getPool();
|
|
95
|
-
const
|
|
122
|
+
const startedAt = Date.now();
|
|
123
|
+
let res;
|
|
124
|
+
try {
|
|
125
|
+
res = await pool.query(sqlQuery, queryParams);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
// Capture pg's structured fields when present (`code`, `severity`,
|
|
129
|
+
// `routine`) — the SQLSTATE class is the single best signal for
|
|
130
|
+
// operators triaging a query failure (e.g. `42P01` = relation does
|
|
131
|
+
// not exist, `28P01` = bad password, `08001` = unable to connect).
|
|
132
|
+
const durationMs = Date.now() - startedAt;
|
|
133
|
+
const errAny = err;
|
|
134
|
+
dbLog.error('Postgres query failed', {
|
|
135
|
+
durationMs,
|
|
136
|
+
sqlPreview: previewSql(sqlQuery),
|
|
137
|
+
paramCount: queryParams?.length ?? 0,
|
|
138
|
+
errorName: err instanceof Error ? err.name : undefined,
|
|
139
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
140
|
+
pgCode: errAny.code,
|
|
141
|
+
pgSeverity: errAny.severity,
|
|
142
|
+
pgRoutine: errAny.routine,
|
|
143
|
+
});
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
const durationMs = Date.now() - startedAt;
|
|
147
|
+
const slowMs = resolveSlowQueryThresholdMs();
|
|
148
|
+
if (slowMs > 0 && durationMs >= slowMs) {
|
|
149
|
+
dbLog.warn('Slow Postgres query', {
|
|
150
|
+
durationMs,
|
|
151
|
+
thresholdMs: slowMs,
|
|
152
|
+
rowCount: res.rowCount ?? res.rows.length,
|
|
153
|
+
sqlPreview: previewSql(sqlQuery),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
96
156
|
const mapped = mapResults(res.rows, mapperOptions);
|
|
97
157
|
return resultsMapper ? resultsMapper(mapped) : mapped;
|
|
98
158
|
}
|
package/dist/query/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/query/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAA8B,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/query/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAA8B,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,CAAC;AAErD,SAAS,2BAA2B;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IACnD,IAAI,CAAC,GAAG;QAAE,OAAO,+BAA+B,CAAC;IACjD,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC;AAC5E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,OAAO,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AACrE,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,UAAU,EACV,MAAM,EACN,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,QAAgB,EAChB,WAAuB,EACvB,aAAgC,EAChC,aAA6B;IAE7B,sEAAsE;IACtE,0EAA0E;IAC1E,8EAA8E;IAC9E,6CAA6C;IAC7C,MAAM,kBAAkB,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,GAAgB,CAAC;IACrB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,mEAAmE;QACnE,gEAAgE;QAChE,mEAAmE;QACnE,mEAAmE;QACnE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAC1C,MAAM,MAAM,GAAG,GAA6D,CAAC;QAC7E,KAAK,CAAC,KAAK,CAAC,uBAAuB,EAAE;YACnC,UAAU;YACV,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC;YAChC,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;YACpC,SAAS,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YACtD,YAAY,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YAC9D,MAAM,EAAE,MAAM,CAAC,IAAI;YACnB,UAAU,EAAE,MAAM,CAAC,QAAQ;YAC3B,SAAS,EAAE,MAAM,CAAC,OAAO;SAC1B,CAAC,CAAC;QACH,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAG,2BAA2B,EAAE,CAAC;IAC7C,IAAI,MAAM,GAAG,CAAC,IAAI,UAAU,IAAI,MAAM,EAAE,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,qBAAqB,EAAE;YAChC,UAAU;YACV,WAAW,EAAE,MAAM;YACnB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM;YACzC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC;SACjC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACnD,OAAO,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAsB,CAAC;AACxE,CAAC"}
|
package/dist/query/pool.d.ts
CHANGED
|
@@ -14,8 +14,23 @@
|
|
|
14
14
|
* - DB_SSL_CA (PEM-encoded CA bundle to trust, e.g. the RDS global bundle)
|
|
15
15
|
* - DB_SSL_INSECURE ("true" to skip certificate verification — NOT recommended)
|
|
16
16
|
* - DB_POOL_MAX (default 10)
|
|
17
|
+
* - DB_CONNECT_TIMEOUT_MS (default 5000)
|
|
18
|
+
*
|
|
19
|
+
* The connection-timeout default is intentionally well below the 10 s
|
|
20
|
+
* Lambda timeout used by the `nano` / `micro` presets: an unreachable
|
|
21
|
+
* RDS (security-group misconfig, wrong VPC, DB still booting) then
|
|
22
|
+
* surfaces as a clean `pg` error long before the Lambda is killed
|
|
23
|
+
* with no logs.
|
|
17
24
|
*/
|
|
18
25
|
import { Pool } from 'pg';
|
|
26
|
+
/**
|
|
27
|
+
* Default `pg.Pool#connectionTimeoutMillis`. 5 s strikes the same
|
|
28
|
+
* balance as `DEFAULT_SECRETS_FETCH_TIMEOUT_MS` — fast enough that the
|
|
29
|
+
* Lambda emits a structured error inside its own budget, slow enough
|
|
30
|
+
* that healthy cold-start TCP+TLS handshakes (typically 200–1000 ms
|
|
31
|
+
* to RDS Postgres) don't get false-positive aborts.
|
|
32
|
+
*/
|
|
33
|
+
export declare const DEFAULT_CONNECT_TIMEOUT_MS = 5000;
|
|
19
34
|
/**
|
|
20
35
|
* Bridge `DATABASE_URL` into the granular `DB_*` slots `getPool()` reads.
|
|
21
36
|
* Idempotent — only fills slots that aren't already set, so the granular
|
package/dist/query/pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/query/pool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/query/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,IAAI,EAAmB,MAAM,IAAI,CAAC;AAK3C;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,OAAQ,CAAC;AAShD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAoC5C;AAwBD,wBAAgB,OAAO,IAAI,IAAI,CAiD9B"}
|
package/dist/query/pool.js
CHANGED
|
@@ -14,9 +14,32 @@
|
|
|
14
14
|
* - DB_SSL_CA (PEM-encoded CA bundle to trust, e.g. the RDS global bundle)
|
|
15
15
|
* - DB_SSL_INSECURE ("true" to skip certificate verification — NOT recommended)
|
|
16
16
|
* - DB_POOL_MAX (default 10)
|
|
17
|
+
* - DB_CONNECT_TIMEOUT_MS (default 5000)
|
|
18
|
+
*
|
|
19
|
+
* The connection-timeout default is intentionally well below the 10 s
|
|
20
|
+
* Lambda timeout used by the `nano` / `micro` presets: an unreachable
|
|
21
|
+
* RDS (security-group misconfig, wrong VPC, DB still booting) then
|
|
22
|
+
* surfaces as a clean `pg` error long before the Lambda is killed
|
|
23
|
+
* with no logs.
|
|
17
24
|
*/
|
|
18
25
|
import { Pool } from 'pg';
|
|
26
|
+
import { dbLog } from '../internal/logger.js';
|
|
19
27
|
let pool = null;
|
|
28
|
+
/**
|
|
29
|
+
* Default `pg.Pool#connectionTimeoutMillis`. 5 s strikes the same
|
|
30
|
+
* balance as `DEFAULT_SECRETS_FETCH_TIMEOUT_MS` — fast enough that the
|
|
31
|
+
* Lambda emits a structured error inside its own budget, slow enough
|
|
32
|
+
* that healthy cold-start TCP+TLS handshakes (typically 200–1000 ms
|
|
33
|
+
* to RDS Postgres) don't get false-positive aborts.
|
|
34
|
+
*/
|
|
35
|
+
export const DEFAULT_CONNECT_TIMEOUT_MS = 5_000;
|
|
36
|
+
function resolveConnectionTimeoutMs() {
|
|
37
|
+
const raw = process.env.DB_CONNECT_TIMEOUT_MS;
|
|
38
|
+
if (!raw)
|
|
39
|
+
return DEFAULT_CONNECT_TIMEOUT_MS;
|
|
40
|
+
const n = Number.parseInt(raw, 10);
|
|
41
|
+
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_CONNECT_TIMEOUT_MS;
|
|
42
|
+
}
|
|
20
43
|
/**
|
|
21
44
|
* Bridge `DATABASE_URL` into the granular `DB_*` slots `getPool()` reads.
|
|
22
45
|
* Idempotent — only fills slots that aren't already set, so the granular
|
|
@@ -84,14 +107,46 @@ function resolveSsl() {
|
|
|
84
107
|
export function getPool() {
|
|
85
108
|
if (!pool) {
|
|
86
109
|
applyDatabaseUrlToEnv();
|
|
110
|
+
const ssl = resolveSsl();
|
|
111
|
+
const max = Number(process.env.DB_POOL_MAX ?? 10);
|
|
112
|
+
const connectionTimeoutMillis = resolveConnectionTimeoutMs();
|
|
113
|
+
const host = process.env.DB_HOST;
|
|
114
|
+
const port = Number(process.env.DB_PORT ?? 5432);
|
|
115
|
+
const database = process.env.DB_NAME;
|
|
116
|
+
// Log the resolved pool config (sans credentials) once on first
|
|
117
|
+
// `getPool()`. Operators staring at a hung Lambda need this line
|
|
118
|
+
// to confirm DB_HOST / DB_PORT / DB_NAME landed in the expected
|
|
119
|
+
// slots; without it, the only signal that env vars exist at all
|
|
120
|
+
// is a successful query — which is exactly what they don't have.
|
|
121
|
+
dbLog.info('Creating Postgres pool', {
|
|
122
|
+
host,
|
|
123
|
+
port,
|
|
124
|
+
database,
|
|
125
|
+
// Only report whether credentials are present, never their values.
|
|
126
|
+
userPresent: Boolean(process.env.DB_USER),
|
|
127
|
+
passwordPresent: Boolean(process.env.DB_PASSWORD),
|
|
128
|
+
ssl: ssl !== undefined,
|
|
129
|
+
max,
|
|
130
|
+
connectionTimeoutMillis,
|
|
131
|
+
});
|
|
87
132
|
pool = new Pool({
|
|
88
|
-
host
|
|
89
|
-
port
|
|
90
|
-
database
|
|
133
|
+
host,
|
|
134
|
+
port,
|
|
135
|
+
database,
|
|
91
136
|
user: process.env.DB_USER,
|
|
92
137
|
password: process.env.DB_PASSWORD,
|
|
93
|
-
ssl
|
|
94
|
-
max
|
|
138
|
+
ssl,
|
|
139
|
+
max,
|
|
140
|
+
connectionTimeoutMillis,
|
|
141
|
+
});
|
|
142
|
+
// Async pool errors (e.g. an idle client losing its TCP connection)
|
|
143
|
+
// would otherwise crash the Lambda with no breadcrumb. Capture them
|
|
144
|
+
// in the structured log so CloudWatch shows what blew up.
|
|
145
|
+
pool.on('error', (err) => {
|
|
146
|
+
dbLog.error('Postgres pool emitted error event', {
|
|
147
|
+
errorName: err.name,
|
|
148
|
+
errorMessage: err.message,
|
|
149
|
+
});
|
|
95
150
|
});
|
|
96
151
|
}
|
|
97
152
|
return pool;
|
package/dist/query/pool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/query/pool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/query/pool.ts"],"names":[],"mappings":"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"}
|
package/dist/query/secret.d.ts
CHANGED
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
* concurrent `query()` calls during cold start share one network round
|
|
20
20
|
* trip rather than racing N of them.
|
|
21
21
|
*
|
|
22
|
+
* The fetch is bounded by an `AbortController` (default 5 s, override
|
|
23
|
+
* via `DB_SECRET_FETCH_TIMEOUT_MS`). VPC-attached Lambdas without a
|
|
24
|
+
* route to Secrets Manager (no NAT, no `com.amazonaws.<region>.secretsmanager`
|
|
25
|
+
* VPC endpoint) would otherwise hang silently until the Lambda's own
|
|
26
|
+
* timeout fires with zero diagnostic output. The bounded fetch raises
|
|
27
|
+
* an actionable error pointing at the likely network fix instead.
|
|
28
|
+
*
|
|
22
29
|
* No-op when:
|
|
23
30
|
* - `DB_SECRET_ARN` is unset (local dev, custom credentials), or
|
|
24
31
|
* - both `DB_USER` and `DB_PASSWORD` are already set (e.g. the
|
|
@@ -30,6 +37,16 @@
|
|
|
30
37
|
* environments using a `DATABASE_URL` against a local Postgres) don't
|
|
31
38
|
* blow up at module load.
|
|
32
39
|
*/
|
|
40
|
+
/**
|
|
41
|
+
* Default timeout for the Secrets Manager `GetSecretValue` call.
|
|
42
|
+
* 5 s is well below the 10 s default Lambda timeout used by the `nano`
|
|
43
|
+
* and `micro` presets, so a hung fetch surfaces as a clear error rather
|
|
44
|
+
* than as a Lambda-level timeout with no logs.
|
|
45
|
+
*
|
|
46
|
+
* Override via `DB_SECRET_FETCH_TIMEOUT_MS` per environment if your
|
|
47
|
+
* Lambda has a longer budget.
|
|
48
|
+
*/
|
|
49
|
+
export declare const DEFAULT_SECRETS_FETCH_TIMEOUT_MS = 5000;
|
|
33
50
|
export declare function applyDbSecretToEnv(): Promise<void>;
|
|
34
51
|
/**
|
|
35
52
|
* Reset the memoized resolution. Test-only escape hatch — exposed under
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../../src/query/secret.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../../src/query/secret.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAKH;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,OAAQ,CAAC;AAsCtD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBxD;AAoHD;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
package/dist/query/secret.js
CHANGED
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
* concurrent `query()` calls during cold start share one network round
|
|
20
20
|
* trip rather than racing N of them.
|
|
21
21
|
*
|
|
22
|
+
* The fetch is bounded by an `AbortController` (default 5 s, override
|
|
23
|
+
* via `DB_SECRET_FETCH_TIMEOUT_MS`). VPC-attached Lambdas without a
|
|
24
|
+
* route to Secrets Manager (no NAT, no `com.amazonaws.<region>.secretsmanager`
|
|
25
|
+
* VPC endpoint) would otherwise hang silently until the Lambda's own
|
|
26
|
+
* timeout fires with zero diagnostic output. The bounded fetch raises
|
|
27
|
+
* an actionable error pointing at the likely network fix instead.
|
|
28
|
+
*
|
|
22
29
|
* No-op when:
|
|
23
30
|
* - `DB_SECRET_ARN` is unset (local dev, custom credentials), or
|
|
24
31
|
* - both `DB_USER` and `DB_PASSWORD` are already set (e.g. the
|
|
@@ -30,6 +37,34 @@
|
|
|
30
37
|
* environments using a `DATABASE_URL` against a local Postgres) don't
|
|
31
38
|
* blow up at module load.
|
|
32
39
|
*/
|
|
40
|
+
import { dbLog } from '../internal/logger.js';
|
|
41
|
+
/**
|
|
42
|
+
* Default timeout for the Secrets Manager `GetSecretValue` call.
|
|
43
|
+
* 5 s is well below the 10 s default Lambda timeout used by the `nano`
|
|
44
|
+
* and `micro` presets, so a hung fetch surfaces as a clear error rather
|
|
45
|
+
* than as a Lambda-level timeout with no logs.
|
|
46
|
+
*
|
|
47
|
+
* Override via `DB_SECRET_FETCH_TIMEOUT_MS` per environment if your
|
|
48
|
+
* Lambda has a longer budget.
|
|
49
|
+
*/
|
|
50
|
+
export const DEFAULT_SECRETS_FETCH_TIMEOUT_MS = 5_000;
|
|
51
|
+
function resolveSecretsFetchTimeoutMs() {
|
|
52
|
+
const raw = process.env.DB_SECRET_FETCH_TIMEOUT_MS;
|
|
53
|
+
if (!raw)
|
|
54
|
+
return DEFAULT_SECRETS_FETCH_TIMEOUT_MS;
|
|
55
|
+
const n = Number.parseInt(raw, 10);
|
|
56
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_SECRETS_FETCH_TIMEOUT_MS;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Strip the ARN prefix down to the trailing `secret:<name>` chunk so
|
|
60
|
+
* structured logs don't leak the AWS account number / region in plain
|
|
61
|
+
* text. Returns the input unchanged when it doesn't look like an ARN
|
|
62
|
+
* (e.g. unit tests passing a fake id).
|
|
63
|
+
*/
|
|
64
|
+
function redactArn(arn) {
|
|
65
|
+
const idx = arn.lastIndexOf(':');
|
|
66
|
+
return idx === -1 ? arn : arn.slice(idx + 1);
|
|
67
|
+
}
|
|
33
68
|
let resolution = null;
|
|
34
69
|
export async function applyDbSecretToEnv() {
|
|
35
70
|
const arn = process.env.DB_SECRET_ARN;
|
|
@@ -57,7 +92,53 @@ async function fetchAndApply(arn) {
|
|
|
57
92
|
const sm = await import('@aws-sdk/client-secrets-manager');
|
|
58
93
|
const region = process.env.AWS_REGION;
|
|
59
94
|
const client = new sm.SecretsManagerClient(region ? { region } : {});
|
|
60
|
-
const
|
|
95
|
+
const timeoutMs = resolveSecretsFetchTimeoutMs();
|
|
96
|
+
const controller = new AbortController();
|
|
97
|
+
// `unref()` so the timer never keeps the event loop alive past the
|
|
98
|
+
// SDK call's own resolution — Lambda's freeze/thaw cycle would
|
|
99
|
+
// otherwise stall waiting for it on warm invocations.
|
|
100
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
101
|
+
if (typeof timer.unref === 'function')
|
|
102
|
+
timer.unref();
|
|
103
|
+
const startedAt = Date.now();
|
|
104
|
+
const redactedArn = redactArn(arn);
|
|
105
|
+
dbLog.info('Fetching DB credentials from Secrets Manager', {
|
|
106
|
+
secret: redactedArn,
|
|
107
|
+
region: region ?? 'sdk-default',
|
|
108
|
+
timeoutMs,
|
|
109
|
+
});
|
|
110
|
+
let result;
|
|
111
|
+
try {
|
|
112
|
+
result = await client.send(new sm.GetSecretValueCommand({ SecretId: arn }), { abortSignal: controller.signal });
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
const durationMs = Date.now() - startedAt;
|
|
116
|
+
const aborted = controller.signal.aborted;
|
|
117
|
+
const errorName = err instanceof Error ? err.name : undefined;
|
|
118
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
119
|
+
dbLog.error('Failed to fetch DB credentials from Secrets Manager', {
|
|
120
|
+
secret: redactedArn,
|
|
121
|
+
durationMs,
|
|
122
|
+
timedOut: aborted,
|
|
123
|
+
errorName,
|
|
124
|
+
errorMessage,
|
|
125
|
+
});
|
|
126
|
+
if (aborted) {
|
|
127
|
+
// Re-throw with an actionable hint. The most common cause for a
|
|
128
|
+
// VPC-attached Lambda is no route to Secrets Manager — either NAT
|
|
129
|
+
// is unhealthy or there is no SM VPC interface endpoint.
|
|
130
|
+
throw new Error(`[venturekit/data] Timed out (${timeoutMs} ms) fetching DB credentials ` +
|
|
131
|
+
`from Secrets Manager (secret: ${redactedArn}). If the Lambda runs in ` +
|
|
132
|
+
`a VPC, verify it has a route to Secrets Manager: a working NAT gateway/instance, ` +
|
|
133
|
+
`or a com.amazonaws.<region>.secretsmanager VPC interface endpoint. ` +
|
|
134
|
+
`Override the timeout via DB_SECRET_FETCH_TIMEOUT_MS.`);
|
|
135
|
+
}
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
clearTimeout(timer);
|
|
140
|
+
}
|
|
141
|
+
const fetchDurationMs = Date.now() - startedAt;
|
|
61
142
|
const raw = result.SecretString;
|
|
62
143
|
if (!raw) {
|
|
63
144
|
throw new Error(`[venturekit/data] DB_SECRET_ARN points at a secret with no SecretString: ${arn}`);
|
|
@@ -70,23 +151,38 @@ async function fetchAndApply(arn) {
|
|
|
70
151
|
throw new Error('[venturekit/data] DB_SECRET_ARN value is not JSON. ' +
|
|
71
152
|
'Expected an RDS-style secret with at least { username, password } fields.');
|
|
72
153
|
}
|
|
154
|
+
// Track which env slots we populated so the success log makes it
|
|
155
|
+
// obvious whether host/port/name came from the secret or were already
|
|
156
|
+
// wired in by infra. Operators debugging "why is my DB_HOST empty"
|
|
157
|
+
// can grep for this line and see the answer at a glance.
|
|
158
|
+
const slotsApplied = [];
|
|
73
159
|
if (!process.env.DB_USER && parsed.username) {
|
|
74
160
|
process.env.DB_USER = String(parsed.username);
|
|
161
|
+
slotsApplied.push('DB_USER');
|
|
75
162
|
}
|
|
76
163
|
if (!process.env.DB_PASSWORD && parsed.password) {
|
|
77
164
|
process.env.DB_PASSWORD = String(parsed.password);
|
|
165
|
+
slotsApplied.push('DB_PASSWORD');
|
|
78
166
|
}
|
|
79
167
|
if (!process.env.DB_HOST && parsed.host) {
|
|
80
168
|
process.env.DB_HOST = String(parsed.host);
|
|
169
|
+
slotsApplied.push('DB_HOST');
|
|
81
170
|
}
|
|
82
171
|
if (!process.env.DB_PORT &&
|
|
83
172
|
parsed.port !== undefined &&
|
|
84
173
|
parsed.port !== null) {
|
|
85
174
|
process.env.DB_PORT = String(parsed.port);
|
|
175
|
+
slotsApplied.push('DB_PORT');
|
|
86
176
|
}
|
|
87
177
|
if (!process.env.DB_NAME && parsed.dbname) {
|
|
88
178
|
process.env.DB_NAME = String(parsed.dbname);
|
|
179
|
+
slotsApplied.push('DB_NAME');
|
|
89
180
|
}
|
|
181
|
+
dbLog.info('DB credentials applied to env', {
|
|
182
|
+
secret: redactedArn,
|
|
183
|
+
durationMs: fetchDurationMs,
|
|
184
|
+
slotsApplied,
|
|
185
|
+
});
|
|
90
186
|
}
|
|
91
187
|
/**
|
|
92
188
|
* Reset the memoized resolution. Test-only escape hatch — exposed under
|
package/dist/query/secret.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret.js","sourceRoot":"","sources":["../../src/query/secret.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"secret.js","sourceRoot":"","sources":["../../src/query/secret.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/query/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,IAAI,CAAC;AAElD,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/query/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,IAAI,CAAC;AAElD,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAc7D,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACjC,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,EAAE,EACvB,aAAa,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EAChC,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,CAAC,CAAC,CAAC;IACd,6BAA6B;IAC7B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,gCAAgC;IAChC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;OAWG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAUnD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAwCzF;AAaD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACnC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAAC;AACd,wBAAsB,eAAe,CAAC,CAAC,EACrC,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,EAAE,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACnC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAAC;AAkDd;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,CAkDhE"}
|
|
@@ -9,6 +9,16 @@
|
|
|
9
9
|
import { getPool } from './pool.js';
|
|
10
10
|
import { mapResults } from './mapper.js';
|
|
11
11
|
import { applyDbSecretToEnv } from './secret.js';
|
|
12
|
+
import { dbLog } from '../internal/logger.js';
|
|
13
|
+
/**
|
|
14
|
+
* Same single-line clip used by `query()`'s logger. Duplicated here
|
|
15
|
+
* (rather than imported from `./index.js`) to avoid a cycle between
|
|
16
|
+
* the query barrel and the transaction module.
|
|
17
|
+
*/
|
|
18
|
+
function previewSql(sql) {
|
|
19
|
+
const single = sql.replace(/\s+/g, ' ').trim();
|
|
20
|
+
return single.length > 120 ? `${single.slice(0, 117)}...` : single;
|
|
21
|
+
}
|
|
12
22
|
/**
|
|
13
23
|
* Default statement timeout (ms) — keeps Lambdas from hanging on rogue queries
|
|
14
24
|
* while staying generous enough for normal OLTP work. Override per-call via
|
|
@@ -49,7 +59,27 @@ export async function beginTransaction(options) {
|
|
|
49
59
|
// memoized — see `applyDbSecretToEnv` for details.
|
|
50
60
|
await applyDbSecretToEnv();
|
|
51
61
|
const pool = getPool();
|
|
52
|
-
|
|
62
|
+
// `pool.connect()` is the most likely place a misconfigured network
|
|
63
|
+
// surfaces (security group blocking 5432, RDS in a different VPC,
|
|
64
|
+
// wrong DB_HOST). Wrapping it in start/error logs gives operators a
|
|
65
|
+
// breadcrumb between "Creating Postgres pool" and the eventual
|
|
66
|
+
// Lambda timeout that they otherwise wouldn't have.
|
|
67
|
+
const connectStartedAt = Date.now();
|
|
68
|
+
let client;
|
|
69
|
+
try {
|
|
70
|
+
client = await pool.connect();
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const durationMs = Date.now() - connectStartedAt;
|
|
74
|
+
const errAny = err;
|
|
75
|
+
dbLog.error('Postgres pool.connect() failed', {
|
|
76
|
+
durationMs,
|
|
77
|
+
errorName: err instanceof Error ? err.name : undefined,
|
|
78
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
79
|
+
pgCode: errAny.code,
|
|
80
|
+
});
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
53
83
|
await client.query('BEGIN');
|
|
54
84
|
const timeoutMs = resolveStatementTimeout(options);
|
|
55
85
|
if (timeoutMs > 0) {
|
|
@@ -123,7 +153,29 @@ export async function withTransaction(fnOrOuter, fnOrOptions, maybeOptions) {
|
|
|
123
153
|
export function buildTransaction(client) {
|
|
124
154
|
return {
|
|
125
155
|
async query(sqlQuery, queryParams, resultsMapper, mapperOptions) {
|
|
126
|
-
const
|
|
156
|
+
const startedAt = Date.now();
|
|
157
|
+
let res;
|
|
158
|
+
try {
|
|
159
|
+
res = await client.query(sqlQuery, queryParams);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
// Surface pg's structured error fields just like the top-level
|
|
163
|
+
// `query()` does, so transactional and non-transactional code
|
|
164
|
+
// paths emit identical error breadcrumbs.
|
|
165
|
+
const durationMs = Date.now() - startedAt;
|
|
166
|
+
const errAny = err;
|
|
167
|
+
dbLog.error('Postgres transactional query failed', {
|
|
168
|
+
durationMs,
|
|
169
|
+
sqlPreview: previewSql(sqlQuery),
|
|
170
|
+
paramCount: queryParams?.length ?? 0,
|
|
171
|
+
errorName: err instanceof Error ? err.name : undefined,
|
|
172
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
173
|
+
pgCode: errAny.code,
|
|
174
|
+
pgSeverity: errAny.severity,
|
|
175
|
+
pgRoutine: errAny.routine,
|
|
176
|
+
});
|
|
177
|
+
throw err;
|
|
178
|
+
}
|
|
127
179
|
const mapped = mapResults(res.rows, mapperOptions);
|
|
128
180
|
return resultsMapper ? resultsMapper(mapped) : mapped;
|
|
129
181
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/query/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAsB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/query/transaction.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venturekit/data",
|
|
3
|
-
"version": "0.0.0-dev.
|
|
3
|
+
"version": "0.0.0-dev.20260505164727",
|
|
4
4
|
"description": "Database and data layer for VentureKit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@aws-sdk/client-secrets-manager": "^3.500.0",
|
|
29
|
-
"@venturekit/core": "0.0.0-dev.
|
|
29
|
+
"@venturekit/core": "0.0.0-dev.20260505164727",
|
|
30
30
|
"pg": "^8.12.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|