@teamkeel/functions-runtime 0.393.0 → 0.393.2

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.
Files changed (2) hide show
  1. package/package.json +2 -3
  2. package/src/database.js +55 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamkeel/functions-runtime",
3
- "version": "0.393.0",
3
+ "version": "0.393.2",
4
4
  "description": "Internal package used by @teamkeel/sdk",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -21,7 +21,7 @@
21
21
  "dependencies": {
22
22
  "@aws-sdk/client-s3": "^3.617.0",
23
23
  "@aws-sdk/credential-providers": "^3.617.0",
24
- "@neondatabase/serverless": "^0.9.3",
24
+ "@neondatabase/serverless": "^0.9.4",
25
25
  "@opentelemetry/api": "^1.7.0",
26
26
  "@opentelemetry/exporter-trace-otlp-proto": "^0.46.0",
27
27
  "@opentelemetry/resources": "^1.19.0",
@@ -31,7 +31,6 @@
31
31
  "json-rpc-2.0": "^1.7.0",
32
32
  "ksuid": "^3.0.0",
33
33
  "kysely": "^0.25.0",
34
- "kysely-neon": "^1.3.0",
35
34
  "pg": "^8.11.3",
36
35
  "traceparent": "^1.0.0",
37
36
  "ws": "^8.17.1"
package/src/database.js CHANGED
@@ -1,10 +1,10 @@
1
1
  const { Kysely, PostgresDialect, CamelCasePlugin } = require("kysely");
2
+ const neonserverless = require("@neondatabase/serverless");
2
3
  const { AsyncLocalStorage } = require("async_hooks");
3
4
  const { AuditContextPlugin } = require("./auditing");
4
5
  const pg = require("pg");
5
6
  const { PROTO_ACTION_TYPES } = require("./consts");
6
7
  const { withSpan } = require("./tracing");
7
- const { NeonDialect } = require("kysely-neon");
8
8
  const ws = require("ws");
9
9
 
10
10
  // withDatabase is responsible for setting the correct database client in our AsyncLocalStorage
@@ -107,7 +107,20 @@ function getDatabaseClient() {
107
107
  class InstrumentedPool extends pg.Pool {
108
108
  async connect(...args) {
109
109
  const _super = super.connect.bind(this);
110
- return withSpan("Database Connect", function () {
110
+ return withSpan("Database Connect", function (span) {
111
+ span.setAttribute("dialect", process.env["KEEL_DB_CONN_TYPE"]);
112
+ span.setAttribute("timeout", connectionTimeout());
113
+ return _super(...args);
114
+ });
115
+ }
116
+ }
117
+
118
+ class InstrumentedNeonServerlessPool extends neonserverless.Pool {
119
+ async connect(...args) {
120
+ const _super = super.connect.bind(this);
121
+ return withSpan("Database Connect", function (span) {
122
+ span.setAttribute("dialect", process.env["KEEL_DB_CONN_TYPE"]);
123
+ span.setAttribute("timeout", connectionTimeout());
111
124
  return _super(...args);
112
125
  });
113
126
  }
@@ -134,6 +147,7 @@ class InstrumentedClient extends pg.Client {
134
147
  return withSpan(spanName, function (span) {
135
148
  if (sqlAttribute) {
136
149
  span.setAttribute("sql", args[0]);
150
+ span.setAttribute("dialect", process.env["KEEL_DB_CONN_TYPE"]);
137
151
  }
138
152
  return _super(...args);
139
153
  });
@@ -165,14 +179,42 @@ function getDialect() {
165
179
  // Although I doubt we will run into these freeze/thaw issues if idleTimeoutMillis is always shorter than the
166
180
  // time is takes for a lambda to freeze (which is not a constant, but could be as short as several minutes,
167
181
  // https://www.pluralsight.com/resources/blog/cloud/how-long-does-aws-lambda-keep-your-idle-functions-around-before-a-cold-start)
168
- idleTimeoutMillis: 120000,
182
+ idleTimeoutMillis: connectionTimeout(),
169
183
  connectionString: mustEnv("KEEL_DB_CONN"),
170
184
  }),
171
185
  });
172
186
  case "neon":
173
- return new NeonDialect({
187
+ neonserverless.neonConfig.webSocketConstructor = ws;
188
+
189
+ const pool = new InstrumentedNeonServerlessPool({
190
+ idleTimeoutMillis: connectionTimeout(),
174
191
  connectionString: mustEnv("KEEL_DB_CONN"),
175
- webSocketConstructor: ws,
192
+ });
193
+
194
+ pool.on("connect", (client) => {
195
+ const originalQuery = client.query;
196
+ client.query = function (...args) {
197
+ const sql = args[0];
198
+
199
+ let sqlAttribute = false;
200
+ let spanName = txStatements[sql.toLowerCase()];
201
+ if (!spanName) {
202
+ spanName = "Database Query";
203
+ sqlAttribute = true;
204
+ }
205
+
206
+ return withSpan(spanName, function (span) {
207
+ if (sqlAttribute) {
208
+ span.setAttribute("sql", args[0]);
209
+ span.setAttribute("dialect", process.env["KEEL_DB_CONN_TYPE"]);
210
+ }
211
+ return originalQuery.apply(client, args);
212
+ });
213
+ };
214
+ });
215
+
216
+ return new PostgresDialect({
217
+ pool: pool,
176
218
  });
177
219
  default:
178
220
  throw Error("unexpected KEEL_DB_CONN_TYPE: " + dbConnType);
@@ -187,6 +229,14 @@ function mustEnv(key) {
187
229
  return v;
188
230
  }
189
231
 
232
+ function connectionTimeout() {
233
+ const v = Number(process.env["KEEL_DB_CONN_TIMEOUT"]);
234
+ if (!v || isNaN(v)) {
235
+ return 45000; // 60s is our current neon suspend default
236
+ }
237
+ return v;
238
+ }
239
+
190
240
  // initialise the database client at module scope level so the db variable is set
191
241
  getDatabaseClient();
192
242