@vrplatform/kysely 1.3.45-stage.261 → 1.3.45-stage.267
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/build/main/index.js
CHANGED
|
@@ -46,6 +46,9 @@ function isRetryableConnectionError(error) {
|
|
|
46
46
|
const message = error instanceof Error ? error.message : String(error);
|
|
47
47
|
return retryableMessages.some((retryable) => message.includes(retryable));
|
|
48
48
|
}
|
|
49
|
+
function isConnectionReset(error) {
|
|
50
|
+
return (error instanceof Error && 'code' in error && error.code === 'ECONNRESET');
|
|
51
|
+
}
|
|
49
52
|
function retryPostgres(operation, retry) {
|
|
50
53
|
return (0, exponential_backoff_1.backOff)(operation, {
|
|
51
54
|
numOfAttempts: postgresRetryAttempts,
|
|
@@ -81,8 +84,9 @@ class RetryingPostgresJSDialect extends kysely_postgres_js_1.PostgresJSDialect {
|
|
|
81
84
|
if (state.inTransaction ||
|
|
82
85
|
(!isRetryableConnectionError(error) &&
|
|
83
86
|
(compiledQuery.query.kind !== 'SelectQueryNode' ||
|
|
84
|
-
(
|
|
85
|
-
|
|
87
|
+
(!isConnectionReset(error) &&
|
|
88
|
+
message !==
|
|
89
|
+
'Egress connection severed outside of Hyperdrive' &&
|
|
86
90
|
message !== 'Network connection lost.' &&
|
|
87
91
|
message !== 'Node shutting down')))) {
|
|
88
92
|
return false;
|
|
@@ -146,7 +150,7 @@ function useKysely(postgres, options) {
|
|
|
146
150
|
console.debug('Creating Kysely instance');
|
|
147
151
|
const reserveConnection = postgres.reserve.bind(postgres);
|
|
148
152
|
postgres.reserve = async () => {
|
|
149
|
-
const connection = await retryPostgres(reserveConnection, isRetryableConnectionError);
|
|
153
|
+
const connection = await retryPostgres(reserveConnection, (error) => isRetryableConnectionError(error) || isConnectionReset(error));
|
|
150
154
|
if (options?.hyperdrive) {
|
|
151
155
|
const unsafe = connection.unsafe;
|
|
152
156
|
connection.unsafe = (query, parameters, queryOptions) => unsafe(query, parameters, { ...queryOptions, prepare: true });
|
package/build/main/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAsLA,8BA8BC;AAGD,4CAmDC;AAED,wCAMC;AAED,gEAMC;AAED,sDAUC;AAtSD,6DAA8C;AAQ9C,2DAI4B;AAC5B,wDAA8C;AAC9C,mDAA8E;AAC9E,mCAAsC;AACtC,uCAAsC;AAGtC,0CAAwB;AACxB,+CAA6B;AAC7B,mDAAiC;AACjC,0CAAwB;AACxB,6CAA2B;AAC3B,gDAA8B;AAE9B,6CAAkD;AAelD,MAAM,iBAAiB,GAAG;IACxB,mBAAmB;IACnB,iBAAiB;IACjB,uCAAuC;IACvC,oBAAoB;CACrB,CAAC;AACF,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEhC,SAAS,0BAA0B,CAAC,KAAc;IAChD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,aAAa,CACpB,SAA2B,EAC3B,KAA4E;IAE5E,OAAO,IAAA,6BAAO,EAAC,SAAS,EAAE;QACxB,aAAa,EAAE,qBAAqB;QACpC,aAAa,EAAE,IAAA,qBAAa,EAAC,IAAI,CAAC;QAClC,QAAQ,EAAE,IAAA,qBAAa,EAAC,IAAI,CAAC;QAC7B,KAAK,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,CAC9B,aAAa,GAAG,qBAAqB,IAAI,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC;KACvE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,yBAA0B,SAAQ,sCAAiB;IACvD,YAA6B,MAA+B;QAC1D,KAAK,CAAC,MAAM,CAAC,CAAC;QADa,WAAM,GAAN,MAAM,CAAyB;IAE5D,CAAC;IAEQ,YAAY;QACnB,MAAM,MAAM,GAAG,IAAI,qCAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,IAAI,OAAO,EAG5B,CAAC;QACJ,MAAM,aAAa,GAAG,CAAC,UAA8B,EAAE,EAAE;YACvD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;YACxE,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,OAAO;YACL,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;YACzB,iBAAiB,EAAE,KAAK,IAAI,EAAE;gBAC5B,MAAM,KAAK,GAAG;oBACZ,UAAU,EAAE,MAAM,MAAM,CAAC,iBAAiB,EAAE;oBAC5C,aAAa,EAAE,KAAK;iBACrB,CAAC;gBACF,MAAM,UAAU,GAAuB;oBACrC,YAAY,EAAE,CAAC,aAAa,EAAE,EAAE,CAC9B,aAAa,CACX,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,aAAa,CAAC,EAClD,KAAK,EAAE,KAAK,EAAE,EAAE;wBACd,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;wBACzD,IACE,KAAK,CAAC,aAAa;4BACnB,CAAC,CAAC,0BAA0B,CAAC,KAAK,CAAC;gCACjC,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB;oCAC7C,CAAC,OAAO;wCACN,iDAAiD;wCACjD,OAAO,KAAK,0BAA0B;wCACtC,OAAO,KAAK,oBAAoB,CAAC,CAAC,CAAC,EACzC,CAAC;4BACD,OAAO,KAAK,CAAC;wBACf,CAAC;wBAED,4DAA4D;wBAC5D,4DAA4D;wBAC5D,KAAK,CAAC,UAAU,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;wBACpD,OAAO,IAAI,CAAC;oBACd,CAAC,CACF;oBACH,WAAW,EAAE,CAAC,aAAa,EAAE,SAAS,EAAE,EAAE;wBACxC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;4BAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;wBAC5D,CAAC;wBACD,OAAO,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;oBAChE,CAAC;iBACF,CAAC;gBACF,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;gBACnC,OAAO,UAAU,CAAC;YACpB,CAAC;YACD,gBAAgB,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE;gBAC/C,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;gBACxC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC3B,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBAC5D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;oBAC5B,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YACD,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACtC,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;gBACxC,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACnD,CAAC;wBAAS,CAAC;oBACT,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,mBAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACxC,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;gBACxC,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACrD,CAAC;wBAAS,CAAC;oBACT,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,SAAS,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,CACrD,MAAM,CAAC,SAAS,CACd,aAAa,CAAC,UAAU,CAAC,CAAC,UAAU,EACpC,aAAa,EACb,YAAY,CACb;YACH,mBAAmB,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,CAC/D,MAAM,CAAC,mBAAmB,CACxB,aAAa,CAAC,UAAU,CAAC,CAAC,UAAU,EACpC,aAAa,EACb,YAAY,CACb;YACH,gBAAgB,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,CAC5D,MAAM,CAAC,gBAAgB,CACrB,aAAa,CAAC,UAAU,CAAC,CAAC,UAAU,EACpC,aAAa,EACb,YAAY,CACb;YACH,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACtC,MAAM,MAAM,CAAC,iBAAiB,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,CAAC;gBACrE,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACjC,CAAC;YACD,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE;SAChC,CAAC;IACJ,CAAC;CACF;AAKD,SAAgB,SAAS,CAAgB,QAAa,EAAE,OAAoB;IAC1E,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC1C,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,QAAQ,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE;QAC5B,MAAM,UAAU,GAAG,MAAM,aAAa,CACpC,iBAAiB,EACjB,0BAA0B,CAC3B,CAAC;QACF,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;YACjC,UAAU,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,CACtD,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,GAAG,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,IAAA,mBAAS,EACtB,IAAI,yBAAyB,CAAC,EAAE,QAAQ,EAAE,CAAC,EAC3C;QACE,cAAc,EAAE,OAAO,EAAE,cAAc;QACvC,GAAG,EAAE,OAAO,EAAE,GAAG;KAClB,CACF,CAAC;IACF,MAAM,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE;QAC1B,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC3C,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,IAAI,YAAY,GAAmB,EAAE,CAAC;AAC/B,KAAK,UAAU,gBAAgB,CAAC,gBAAwB,EAAE,GAAW;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC;IACrB,MAAM,KAAK,GAAG,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,GAAG,EAAE,eAAe,KAAK,IAAI,IAAI,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC;IACtE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAEtC,OAAO,CAAC,KAAK,CACX,2CAA2C,KAAK,KAAK,OAAO,kBAAkB,GAAG,cAAc,GAAG,CAAC,IAAI,EAAE,CAC1G,CAAC;IACF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,mBAAmB,YAAY,CAAC,MAAM,uBAAuB,CAAC,CAAC;IAE9E,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAA,kBAAQ,EAAC,gBAAgB,EAAE;gBACrC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK;gBAC5B,oBAAoB,EAAE,YAAY;gBAClC,iFAAiF;gBACjF,OAAO,EAAE,IAAI;gBACb,GAAG,CAAC,GAAG,EAAE,UAAU;oBACjB,CAAC,CAAC;wBACE,GAAG,EAAE,CAAC;wBACN,uEAAuE;wBACvE,YAAY,EAAE,EAAE;qBACjB;oBACH,CAAC,CAAC;wBACE,eAAe,EAAE,EAAE;wBACnB,YAAY,EAAE,EAAE;qBACjB,CAAC;aACP,CAAC,CAAC;YAEH,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,GAAG,CAAA,UAAU,CAAC;YACtB,CAAC;YACD,wEAAwE;YACxE,8DAA8D;YAC9D,qEAAqE;YAErE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,OAAO,KAAK,OAAO;gBAAE,MAAM,GAAG,CAAC;YACnC,OAAO,CAAC,IAAI,CACV,uCAAuC,OAAO,gBAAgB,CAC/D,CAAC;YACF,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC5B,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IACD,MAAM,IAAI,mBAAW,CAAC,+BAA+B,CAAC,CAAC;AACzD,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,gBAAwB,EACxB,GAAwB;IAExB,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC;AAEM,KAAK,UAAU,0BAA0B,CAC9C,gBAAwB,EACxB,GAAwB;IAExB,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,IAAA,sCAAsB,EAAC,SAAS,CAAiB,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAEM,KAAK,UAAU,qBAAqB,CAAC,SAAS,GAAG,IAAI;IAC1D,MAAM,OAAO,CAAC,IAAI,CAAC;QACjB,OAAO,CAAC,GAAG,CACT,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CACtB,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAC7D,CACF;QACD,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC;KACxD,CAAC,CAAC;IACH,YAAY,GAAG,EAAE,CAAC;AACpB,CAAC","sourcesContent":["import { backOff } from 'exponential-backoff';\nimport type {\n DatabaseConnection,\n Driver,\n Kysely as K,\n LogConfig,\n Transaction as T,\n} from 'kysely';\nimport {\n PostgresJSDialect,\n type PostgresJSDialectConfig,\n PostgresJSDriver,\n} from 'kysely-postgres-js';\nimport postgres, { type Sql } from 'postgres';\nimport { type ControlPlaneDB, withControlPlaneSchema } from './control-plane';\nimport { KyselyError } from './error';\nimport { getKysely } from './plugins';\n\nexport type { Insertable, LogEvent } from 'kysely';\nexport * from './error';\nexport * from './isomorphic';\nexport * from './postgres-error';\nexport * from './query';\nexport * from './regional';\nexport * from './transaction';\n\nimport { parseDuration } from '@vrplatform/utils';\nimport type { DB } from './v1.generated';\n\ntype KyselyOpts = {\n hyperdrive?: true;\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\ntype PgOpt = {\n forceDisableSSL?: boolean;\n probe?: true;\n retries?: false | number;\n} & Pick<KyselyOpts, 'hyperdrive'>;\n\nconst retryableMessages = [\n 'CONNECTION_CLOSED',\n 'CONNECT_TIMEOUT',\n 'Idle connection closed by Hyperdrive.',\n 'server_login_retry',\n];\nconst postgresRetryAttempts = 3;\n\nfunction isRetryableConnectionError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return retryableMessages.some((retryable) => message.includes(retryable));\n}\n\nfunction retryPostgres<T>(\n operation: () => Promise<T>,\n retry: (error: unknown, attemptNumber: number) => boolean | Promise<boolean>\n) {\n return backOff(operation, {\n numOfAttempts: postgresRetryAttempts,\n startingDelay: parseDuration('1s'),\n maxDelay: parseDuration('5s'),\n retry: (error, attemptNumber) =>\n attemptNumber < postgresRetryAttempts && retry(error, attemptNumber),\n });\n}\n\nclass RetryingPostgresJSDialect extends PostgresJSDialect {\n constructor(private readonly config: PostgresJSDialectConfig) {\n super(config);\n }\n\n override createDriver(): Driver {\n const driver = new PostgresJSDriver(this.config);\n const connections = new WeakMap<\n DatabaseConnection,\n { connection: DatabaseConnection; inTransaction: boolean }\n >();\n const getConnection = (connection: DatabaseConnection) => {\n const state = connections.get(connection);\n if (!state) throw new Error('Postgres connection state is unavailable');\n return state;\n };\n\n return {\n init: () => driver.init(),\n acquireConnection: async () => {\n const state = {\n connection: await driver.acquireConnection(),\n inTransaction: false,\n };\n const connection: DatabaseConnection = {\n executeQuery: (compiledQuery) =>\n retryPostgres(\n () => state.connection.executeQuery(compiledQuery),\n async (error) => {\n const message =\n error instanceof Error ? error.message : String(error);\n if (\n state.inTransaction ||\n (!isRetryableConnectionError(error) &&\n (compiledQuery.query.kind !== 'SelectQueryNode' ||\n (message !==\n 'Egress connection severed outside of Hyperdrive' &&\n message !== 'Network connection lost.' &&\n message !== 'Node shutting down')))\n ) {\n return false;\n }\n\n // Postgres.js already ejects a severed reserved connection.\n // Acquire a new reservation before replaying the safe read.\n state.connection = await driver.acquireConnection();\n return true;\n }\n ),\n streamQuery: (compiledQuery, chunkSize) => {\n if (chunkSize === undefined) {\n throw new Error('Postgres stream chunk size is required');\n }\n return state.connection.streamQuery(compiledQuery, chunkSize);\n },\n };\n connections.set(connection, state);\n return connection;\n },\n beginTransaction: async (connection, settings) => {\n const state = getConnection(connection);\n state.inTransaction = true;\n try {\n await driver.beginTransaction(state.connection, settings);\n } catch (error) {\n state.inTransaction = false;\n throw error;\n }\n },\n commitTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.commitTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n rollbackTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.rollbackTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n savepoint: (connection, savepointName, compileQuery) =>\n driver.savepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n rollbackToSavepoint: (connection, savepointName, compileQuery) =>\n driver.rollbackToSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseSavepoint: (connection, savepointName, compileQuery) =>\n driver.releaseSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseConnection: async (connection) => {\n await driver.releaseConnection(getConnection(connection).connection);\n connections.delete(connection);\n },\n destroy: () => driver.destroy(),\n };\n }\n}\n\nexport type Kysely = K<DB>;\nexport type ControlPlaneKysely = K<ControlPlaneDB>;\nexport type ControlPlaneTransaction = T<ControlPlaneDB>;\nexport function useKysely<Database = DB>(postgres: Sql, options?: KyselyOpts) {\n console.debug('Creating Kysely instance');\n const reserveConnection = postgres.reserve.bind(postgres);\n postgres.reserve = async () => {\n const connection = await retryPostgres(\n reserveConnection,\n isRetryableConnectionError\n );\n if (options?.hyperdrive) {\n const unsafe = connection.unsafe;\n connection.unsafe = (query, parameters, queryOptions) =>\n unsafe(query, parameters, { ...queryOptions, prepare: true });\n }\n return connection;\n };\n const kysely = getKysely<Database>(\n new RetryingPostgresJSDialect({ postgres }),\n {\n repositoryName: options?.repositoryName,\n log: options?.log,\n }\n );\n kysely.destroy = async () => {\n console.debug('Closing Kysely connection');\n await postgres.end({ timeout: 5 }).catch(() => undefined);\n const index = _connections.indexOf(postgres);\n if (index !== -1) _connections.splice(index, 1);\n };\n\n return kysely;\n}\n\nlet _connections: postgres.Sql[] = [];\nexport async function useAsyncPostgres(connectionString: string, opt?: PgOpt) {\n const delayMs = 2500;\n const probe = opt?.probe === true;\n const retries = probe ? (opt?.retries === false ? 0 : opt?.retries || 3) : 1;\n const ssl = opt?.forceDisableSSL !== true && opt?.hyperdrive !== true;\n const url = new URL(connectionString);\n\n console.debug(\n `Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${ssl}, and port=${url.port}`\n );\n if (_connections.length > 0)\n console.warn(`We already have ${_connections.length} Postgres connections`);\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const sql = postgres(connectionString, {\n ssl: ssl ? 'require' : false,\n target_session_attrs: 'read-write',\n // enable prepare statements, pgbouncer on crunchy allows for prepared statements\n prepare: true,\n ...(opt?.hyperdrive\n ? {\n max: 5,\n // Retire idle clients before Hyperdrive can close them asynchronously.\n idle_timeout: 10,\n }\n : {\n connect_timeout: 10,\n idle_timeout: 60,\n }),\n });\n\n if (probe) {\n await sql`select 1`;\n }\n // statement_timeout/lock_timeout are role-level settings on the cluster\n // (ALTER ROLE application SET ...) so they cover every pooled\n // connection; per-session SETs here only ever applied to one of them\n\n _connections.push(sql);\n return sql;\n } catch (err) {\n if (attempt === retries) throw err;\n console.warn(\n `Postgres connection failed (attempt ${attempt}), retrying...`\n );\n console.error('error', err);\n await new Promise((res) => setTimeout(res, delayMs));\n }\n }\n throw new KyselyError('Unable to connect to Postgres');\n}\n\nexport async function useAsyncKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return useKysely(sql, opt);\n}\n\nexport async function useAsyncControlPlaneKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return withControlPlaneSchema(useKysely<ControlPlaneDB>(sql, opt), 'public');\n}\n\nexport async function forceCloseAllPostgres(timeoutMs = 5000) {\n await Promise.race([\n Promise.all(\n _connections.map((pg) =>\n pg.end({ timeout: timeoutMs / 1000 }).catch(() => undefined)\n )\n ),\n new Promise((res) => setTimeout(res, timeoutMs + 1000)),\n ]);\n _connections = [];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { backOff } from 'exponential-backoff';\nimport type {\n DatabaseConnection,\n Driver,\n Kysely as K,\n LogConfig,\n Transaction as T,\n} from 'kysely';\nimport {\n PostgresJSDialect,\n type PostgresJSDialectConfig,\n PostgresJSDriver,\n} from 'kysely-postgres-js';\nimport postgres, { type Sql } from 'postgres';\nimport { type ControlPlaneDB, withControlPlaneSchema } from './control-plane';\nimport { KyselyError } from './error';\nimport { getKysely } from './plugins';\n\nexport type { Insertable, LogEvent } from 'kysely';\nexport * from './error';\nexport * from './isomorphic';\nexport * from './postgres-error';\nexport * from './query';\nexport * from './regional';\nexport * from './transaction';\n\nimport { parseDuration } from '@vrplatform/utils';\nimport type { DB } from './v1.generated';\n\ntype KyselyOpts = {\n hyperdrive?: true;\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\ntype PgOpt = {\n forceDisableSSL?: boolean;\n probe?: true;\n retries?: false | number;\n} & Pick<KyselyOpts, 'hyperdrive'>;\n\nconst retryableMessages = [\n 'CONNECTION_CLOSED',\n 'CONNECT_TIMEOUT',\n 'Idle connection closed by Hyperdrive.',\n 'server_login_retry',\n];\nconst postgresRetryAttempts = 3;\n\nfunction isRetryableConnectionError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return retryableMessages.some((retryable) => message.includes(retryable));\n}\n\nfunction isConnectionReset(error: unknown) {\n return (\n error instanceof Error && 'code' in error && error.code === 'ECONNRESET'\n );\n}\n\nfunction retryPostgres<T>(\n operation: () => Promise<T>,\n retry: (error: unknown, attemptNumber: number) => boolean | Promise<boolean>\n) {\n return backOff(operation, {\n numOfAttempts: postgresRetryAttempts,\n startingDelay: parseDuration('1s'),\n maxDelay: parseDuration('5s'),\n retry: (error, attemptNumber) =>\n attemptNumber < postgresRetryAttempts && retry(error, attemptNumber),\n });\n}\n\nclass RetryingPostgresJSDialect extends PostgresJSDialect {\n constructor(private readonly config: PostgresJSDialectConfig) {\n super(config);\n }\n\n override createDriver(): Driver {\n const driver = new PostgresJSDriver(this.config);\n const connections = new WeakMap<\n DatabaseConnection,\n { connection: DatabaseConnection; inTransaction: boolean }\n >();\n const getConnection = (connection: DatabaseConnection) => {\n const state = connections.get(connection);\n if (!state) throw new Error('Postgres connection state is unavailable');\n return state;\n };\n\n return {\n init: () => driver.init(),\n acquireConnection: async () => {\n const state = {\n connection: await driver.acquireConnection(),\n inTransaction: false,\n };\n const connection: DatabaseConnection = {\n executeQuery: (compiledQuery) =>\n retryPostgres(\n () => state.connection.executeQuery(compiledQuery),\n async (error) => {\n const message =\n error instanceof Error ? error.message : String(error);\n if (\n state.inTransaction ||\n (!isRetryableConnectionError(error) &&\n (compiledQuery.query.kind !== 'SelectQueryNode' ||\n (!isConnectionReset(error) &&\n message !==\n 'Egress connection severed outside of Hyperdrive' &&\n message !== 'Network connection lost.' &&\n message !== 'Node shutting down')))\n ) {\n return false;\n }\n\n // Postgres.js already ejects a severed reserved connection.\n // Acquire a new reservation before replaying the safe read.\n state.connection = await driver.acquireConnection();\n return true;\n }\n ),\n streamQuery: (compiledQuery, chunkSize) => {\n if (chunkSize === undefined) {\n throw new Error('Postgres stream chunk size is required');\n }\n return state.connection.streamQuery(compiledQuery, chunkSize);\n },\n };\n connections.set(connection, state);\n return connection;\n },\n beginTransaction: async (connection, settings) => {\n const state = getConnection(connection);\n state.inTransaction = true;\n try {\n await driver.beginTransaction(state.connection, settings);\n } catch (error) {\n state.inTransaction = false;\n throw error;\n }\n },\n commitTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.commitTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n rollbackTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.rollbackTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n savepoint: (connection, savepointName, compileQuery) =>\n driver.savepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n rollbackToSavepoint: (connection, savepointName, compileQuery) =>\n driver.rollbackToSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseSavepoint: (connection, savepointName, compileQuery) =>\n driver.releaseSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseConnection: async (connection) => {\n await driver.releaseConnection(getConnection(connection).connection);\n connections.delete(connection);\n },\n destroy: () => driver.destroy(),\n };\n }\n}\n\nexport type Kysely = K<DB>;\nexport type ControlPlaneKysely = K<ControlPlaneDB>;\nexport type ControlPlaneTransaction = T<ControlPlaneDB>;\nexport function useKysely<Database = DB>(postgres: Sql, options?: KyselyOpts) {\n console.debug('Creating Kysely instance');\n const reserveConnection = postgres.reserve.bind(postgres);\n postgres.reserve = async () => {\n const connection = await retryPostgres(\n reserveConnection,\n (error) => isRetryableConnectionError(error) || isConnectionReset(error)\n );\n if (options?.hyperdrive) {\n const unsafe = connection.unsafe;\n connection.unsafe = (query, parameters, queryOptions) =>\n unsafe(query, parameters, { ...queryOptions, prepare: true });\n }\n return connection;\n };\n const kysely = getKysely<Database>(\n new RetryingPostgresJSDialect({ postgres }),\n {\n repositoryName: options?.repositoryName,\n log: options?.log,\n }\n );\n kysely.destroy = async () => {\n console.debug('Closing Kysely connection');\n await postgres.end({ timeout: 5 }).catch(() => undefined);\n const index = _connections.indexOf(postgres);\n if (index !== -1) _connections.splice(index, 1);\n };\n\n return kysely;\n}\n\nlet _connections: postgres.Sql[] = [];\nexport async function useAsyncPostgres(connectionString: string, opt?: PgOpt) {\n const delayMs = 2500;\n const probe = opt?.probe === true;\n const retries = probe ? (opt?.retries === false ? 0 : opt?.retries || 3) : 1;\n const ssl = opt?.forceDisableSSL !== true && opt?.hyperdrive !== true;\n const url = new URL(connectionString);\n\n console.debug(\n `Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${ssl}, and port=${url.port}`\n );\n if (_connections.length > 0)\n console.warn(`We already have ${_connections.length} Postgres connections`);\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const sql = postgres(connectionString, {\n ssl: ssl ? 'require' : false,\n target_session_attrs: 'read-write',\n // enable prepare statements, pgbouncer on crunchy allows for prepared statements\n prepare: true,\n ...(opt?.hyperdrive\n ? {\n max: 5,\n // Retire idle clients before Hyperdrive can close them asynchronously.\n idle_timeout: 10,\n }\n : {\n connect_timeout: 10,\n idle_timeout: 60,\n }),\n });\n\n if (probe) {\n await sql`select 1`;\n }\n // statement_timeout/lock_timeout are role-level settings on the cluster\n // (ALTER ROLE application SET ...) so they cover every pooled\n // connection; per-session SETs here only ever applied to one of them\n\n _connections.push(sql);\n return sql;\n } catch (err) {\n if (attempt === retries) throw err;\n console.warn(\n `Postgres connection failed (attempt ${attempt}), retrying...`\n );\n console.error('error', err);\n await new Promise((res) => setTimeout(res, delayMs));\n }\n }\n throw new KyselyError('Unable to connect to Postgres');\n}\n\nexport async function useAsyncKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return useKysely(sql, opt);\n}\n\nexport async function useAsyncControlPlaneKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return withControlPlaneSchema(useKysely<ControlPlaneDB>(sql, opt), 'public');\n}\n\nexport async function forceCloseAllPostgres(timeoutMs = 5000) {\n await Promise.race([\n Promise.all(\n _connections.map((pg) =>\n pg.end({ timeout: timeoutMs / 1000 }).catch(() => undefined)\n )\n ),\n new Promise((res) => setTimeout(res, timeoutMs + 1000)),\n ]);\n _connections = [];\n}\n"]}
|
package/build/module/index.js
CHANGED
|
@@ -22,6 +22,9 @@ function isRetryableConnectionError(error) {
|
|
|
22
22
|
const message = error instanceof Error ? error.message : String(error);
|
|
23
23
|
return retryableMessages.some((retryable) => message.includes(retryable));
|
|
24
24
|
}
|
|
25
|
+
function isConnectionReset(error) {
|
|
26
|
+
return (error instanceof Error && 'code' in error && error.code === 'ECONNRESET');
|
|
27
|
+
}
|
|
25
28
|
function retryPostgres(operation, retry) {
|
|
26
29
|
return backOff(operation, {
|
|
27
30
|
numOfAttempts: postgresRetryAttempts,
|
|
@@ -58,8 +61,9 @@ class RetryingPostgresJSDialect extends PostgresJSDialect {
|
|
|
58
61
|
if (state.inTransaction ||
|
|
59
62
|
(!isRetryableConnectionError(error) &&
|
|
60
63
|
(compiledQuery.query.kind !== 'SelectQueryNode' ||
|
|
61
|
-
(
|
|
62
|
-
|
|
64
|
+
(!isConnectionReset(error) &&
|
|
65
|
+
message !==
|
|
66
|
+
'Egress connection severed outside of Hyperdrive' &&
|
|
63
67
|
message !== 'Network connection lost.' &&
|
|
64
68
|
message !== 'Node shutting down')))) {
|
|
65
69
|
return false;
|
|
@@ -123,7 +127,7 @@ export function useKysely(postgres, options) {
|
|
|
123
127
|
console.debug('Creating Kysely instance');
|
|
124
128
|
const reserveConnection = postgres.reserve.bind(postgres);
|
|
125
129
|
postgres.reserve = async () => {
|
|
126
|
-
const connection = await retryPostgres(reserveConnection, isRetryableConnectionError);
|
|
130
|
+
const connection = await retryPostgres(reserveConnection, (error) => isRetryableConnectionError(error) || isConnectionReset(error));
|
|
127
131
|
if (options?.hyperdrive) {
|
|
128
132
|
const unsafe = connection.unsafe;
|
|
129
133
|
connection.unsafe = (query, parameters, queryOptions) => unsafe(query, parameters, { ...queryOptions, prepare: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { backOff } from 'exponential-backoff';\nimport type {\n DatabaseConnection,\n Driver,\n Kysely as K,\n LogConfig,\n Transaction as T,\n} from 'kysely';\nimport {\n PostgresJSDialect,\n type PostgresJSDialectConfig,\n PostgresJSDriver,\n} from 'kysely-postgres-js';\nimport postgres, { type Sql } from 'postgres';\nimport { type ControlPlaneDB, withControlPlaneSchema } from './control-plane';\nimport { KyselyError } from './error';\nimport { getKysely } from './plugins';\n\nexport type { Insertable, LogEvent } from 'kysely';\nexport * from './error';\nexport * from './isomorphic';\nexport * from './postgres-error';\nexport * from './query';\nexport * from './regional';\nexport * from './transaction';\n\nimport { parseDuration } from '@vrplatform/utils';\nimport type { DB } from './v1.generated';\n\ntype KyselyOpts = {\n hyperdrive?: true;\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\ntype PgOpt = {\n forceDisableSSL?: boolean;\n probe?: true;\n retries?: false | number;\n} & Pick<KyselyOpts, 'hyperdrive'>;\n\nconst retryableMessages = [\n 'CONNECTION_CLOSED',\n 'CONNECT_TIMEOUT',\n 'Idle connection closed by Hyperdrive.',\n 'server_login_retry',\n];\nconst postgresRetryAttempts = 3;\n\nfunction isRetryableConnectionError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return retryableMessages.some((retryable) => message.includes(retryable));\n}\n\nfunction retryPostgres<T>(\n operation: () => Promise<T>,\n retry: (error: unknown, attemptNumber: number) => boolean | Promise<boolean>\n) {\n return backOff(operation, {\n numOfAttempts: postgresRetryAttempts,\n startingDelay: parseDuration('1s'),\n maxDelay: parseDuration('5s'),\n retry: (error, attemptNumber) =>\n attemptNumber < postgresRetryAttempts && retry(error, attemptNumber),\n });\n}\n\nclass RetryingPostgresJSDialect extends PostgresJSDialect {\n constructor(private readonly config: PostgresJSDialectConfig) {\n super(config);\n }\n\n override createDriver(): Driver {\n const driver = new PostgresJSDriver(this.config);\n const connections = new WeakMap<\n DatabaseConnection,\n { connection: DatabaseConnection; inTransaction: boolean }\n >();\n const getConnection = (connection: DatabaseConnection) => {\n const state = connections.get(connection);\n if (!state) throw new Error('Postgres connection state is unavailable');\n return state;\n };\n\n return {\n init: () => driver.init(),\n acquireConnection: async () => {\n const state = {\n connection: await driver.acquireConnection(),\n inTransaction: false,\n };\n const connection: DatabaseConnection = {\n executeQuery: (compiledQuery) =>\n retryPostgres(\n () => state.connection.executeQuery(compiledQuery),\n async (error) => {\n const message =\n error instanceof Error ? error.message : String(error);\n if (\n state.inTransaction ||\n (!isRetryableConnectionError(error) &&\n (compiledQuery.query.kind !== 'SelectQueryNode' ||\n (message !==\n 'Egress connection severed outside of Hyperdrive' &&\n message !== 'Network connection lost.' &&\n message !== 'Node shutting down')))\n ) {\n return false;\n }\n\n // Postgres.js already ejects a severed reserved connection.\n // Acquire a new reservation before replaying the safe read.\n state.connection = await driver.acquireConnection();\n return true;\n }\n ),\n streamQuery: (compiledQuery, chunkSize) => {\n if (chunkSize === undefined) {\n throw new Error('Postgres stream chunk size is required');\n }\n return state.connection.streamQuery(compiledQuery, chunkSize);\n },\n };\n connections.set(connection, state);\n return connection;\n },\n beginTransaction: async (connection, settings) => {\n const state = getConnection(connection);\n state.inTransaction = true;\n try {\n await driver.beginTransaction(state.connection, settings);\n } catch (error) {\n state.inTransaction = false;\n throw error;\n }\n },\n commitTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.commitTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n rollbackTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.rollbackTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n savepoint: (connection, savepointName, compileQuery) =>\n driver.savepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n rollbackToSavepoint: (connection, savepointName, compileQuery) =>\n driver.rollbackToSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseSavepoint: (connection, savepointName, compileQuery) =>\n driver.releaseSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseConnection: async (connection) => {\n await driver.releaseConnection(getConnection(connection).connection);\n connections.delete(connection);\n },\n destroy: () => driver.destroy(),\n };\n }\n}\n\nexport type Kysely = K<DB>;\nexport type ControlPlaneKysely = K<ControlPlaneDB>;\nexport type ControlPlaneTransaction = T<ControlPlaneDB>;\nexport function useKysely<Database = DB>(postgres: Sql, options?: KyselyOpts) {\n console.debug('Creating Kysely instance');\n const reserveConnection = postgres.reserve.bind(postgres);\n postgres.reserve = async () => {\n const connection = await retryPostgres(\n reserveConnection,\n isRetryableConnectionError\n );\n if (options?.hyperdrive) {\n const unsafe = connection.unsafe;\n connection.unsafe = (query, parameters, queryOptions) =>\n unsafe(query, parameters, { ...queryOptions, prepare: true });\n }\n return connection;\n };\n const kysely = getKysely<Database>(\n new RetryingPostgresJSDialect({ postgres }),\n {\n repositoryName: options?.repositoryName,\n log: options?.log,\n }\n );\n kysely.destroy = async () => {\n console.debug('Closing Kysely connection');\n await postgres.end({ timeout: 5 }).catch(() => undefined);\n const index = _connections.indexOf(postgres);\n if (index !== -1) _connections.splice(index, 1);\n };\n\n return kysely;\n}\n\nlet _connections: postgres.Sql[] = [];\nexport async function useAsyncPostgres(connectionString: string, opt?: PgOpt) {\n const delayMs = 2500;\n const probe = opt?.probe === true;\n const retries = probe ? (opt?.retries === false ? 0 : opt?.retries || 3) : 1;\n const ssl = opt?.forceDisableSSL !== true && opt?.hyperdrive !== true;\n const url = new URL(connectionString);\n\n console.debug(\n `Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${ssl}, and port=${url.port}`\n );\n if (_connections.length > 0)\n console.warn(`We already have ${_connections.length} Postgres connections`);\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const sql = postgres(connectionString, {\n ssl: ssl ? 'require' : false,\n target_session_attrs: 'read-write',\n // enable prepare statements, pgbouncer on crunchy allows for prepared statements\n prepare: true,\n ...(opt?.hyperdrive\n ? {\n max: 5,\n // Retire idle clients before Hyperdrive can close them asynchronously.\n idle_timeout: 10,\n }\n : {\n connect_timeout: 10,\n idle_timeout: 60,\n }),\n });\n\n if (probe) {\n await sql`select 1`;\n }\n // statement_timeout/lock_timeout are role-level settings on the cluster\n // (ALTER ROLE application SET ...) so they cover every pooled\n // connection; per-session SETs here only ever applied to one of them\n\n _connections.push(sql);\n return sql;\n } catch (err) {\n if (attempt === retries) throw err;\n console.warn(\n `Postgres connection failed (attempt ${attempt}), retrying...`\n );\n console.error('error', err);\n await new Promise((res) => setTimeout(res, delayMs));\n }\n }\n throw new KyselyError('Unable to connect to Postgres');\n}\n\nexport async function useAsyncKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return useKysely(sql, opt);\n}\n\nexport async function useAsyncControlPlaneKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return withControlPlaneSchema(useKysely<ControlPlaneDB>(sql, opt), 'public');\n}\n\nexport async function forceCloseAllPostgres(timeoutMs = 5000) {\n await Promise.race([\n Promise.all(\n _connections.map((pg) =>\n pg.end({ timeout: timeoutMs / 1000 }).catch(() => undefined)\n )\n ),\n new Promise((res) => setTimeout(res, timeoutMs + 1000)),\n ]);\n _connections = [];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { backOff } from 'exponential-backoff';\nimport type {\n DatabaseConnection,\n Driver,\n Kysely as K,\n LogConfig,\n Transaction as T,\n} from 'kysely';\nimport {\n PostgresJSDialect,\n type PostgresJSDialectConfig,\n PostgresJSDriver,\n} from 'kysely-postgres-js';\nimport postgres, { type Sql } from 'postgres';\nimport { type ControlPlaneDB, withControlPlaneSchema } from './control-plane';\nimport { KyselyError } from './error';\nimport { getKysely } from './plugins';\n\nexport type { Insertable, LogEvent } from 'kysely';\nexport * from './error';\nexport * from './isomorphic';\nexport * from './postgres-error';\nexport * from './query';\nexport * from './regional';\nexport * from './transaction';\n\nimport { parseDuration } from '@vrplatform/utils';\nimport type { DB } from './v1.generated';\n\ntype KyselyOpts = {\n hyperdrive?: true;\n repositoryName?: string;\n log?: true | LogConfig;\n};\n\ntype PgOpt = {\n forceDisableSSL?: boolean;\n probe?: true;\n retries?: false | number;\n} & Pick<KyselyOpts, 'hyperdrive'>;\n\nconst retryableMessages = [\n 'CONNECTION_CLOSED',\n 'CONNECT_TIMEOUT',\n 'Idle connection closed by Hyperdrive.',\n 'server_login_retry',\n];\nconst postgresRetryAttempts = 3;\n\nfunction isRetryableConnectionError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return retryableMessages.some((retryable) => message.includes(retryable));\n}\n\nfunction isConnectionReset(error: unknown) {\n return (\n error instanceof Error && 'code' in error && error.code === 'ECONNRESET'\n );\n}\n\nfunction retryPostgres<T>(\n operation: () => Promise<T>,\n retry: (error: unknown, attemptNumber: number) => boolean | Promise<boolean>\n) {\n return backOff(operation, {\n numOfAttempts: postgresRetryAttempts,\n startingDelay: parseDuration('1s'),\n maxDelay: parseDuration('5s'),\n retry: (error, attemptNumber) =>\n attemptNumber < postgresRetryAttempts && retry(error, attemptNumber),\n });\n}\n\nclass RetryingPostgresJSDialect extends PostgresJSDialect {\n constructor(private readonly config: PostgresJSDialectConfig) {\n super(config);\n }\n\n override createDriver(): Driver {\n const driver = new PostgresJSDriver(this.config);\n const connections = new WeakMap<\n DatabaseConnection,\n { connection: DatabaseConnection; inTransaction: boolean }\n >();\n const getConnection = (connection: DatabaseConnection) => {\n const state = connections.get(connection);\n if (!state) throw new Error('Postgres connection state is unavailable');\n return state;\n };\n\n return {\n init: () => driver.init(),\n acquireConnection: async () => {\n const state = {\n connection: await driver.acquireConnection(),\n inTransaction: false,\n };\n const connection: DatabaseConnection = {\n executeQuery: (compiledQuery) =>\n retryPostgres(\n () => state.connection.executeQuery(compiledQuery),\n async (error) => {\n const message =\n error instanceof Error ? error.message : String(error);\n if (\n state.inTransaction ||\n (!isRetryableConnectionError(error) &&\n (compiledQuery.query.kind !== 'SelectQueryNode' ||\n (!isConnectionReset(error) &&\n message !==\n 'Egress connection severed outside of Hyperdrive' &&\n message !== 'Network connection lost.' &&\n message !== 'Node shutting down')))\n ) {\n return false;\n }\n\n // Postgres.js already ejects a severed reserved connection.\n // Acquire a new reservation before replaying the safe read.\n state.connection = await driver.acquireConnection();\n return true;\n }\n ),\n streamQuery: (compiledQuery, chunkSize) => {\n if (chunkSize === undefined) {\n throw new Error('Postgres stream chunk size is required');\n }\n return state.connection.streamQuery(compiledQuery, chunkSize);\n },\n };\n connections.set(connection, state);\n return connection;\n },\n beginTransaction: async (connection, settings) => {\n const state = getConnection(connection);\n state.inTransaction = true;\n try {\n await driver.beginTransaction(state.connection, settings);\n } catch (error) {\n state.inTransaction = false;\n throw error;\n }\n },\n commitTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.commitTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n rollbackTransaction: async (connection) => {\n const state = getConnection(connection);\n try {\n await driver.rollbackTransaction(state.connection);\n } finally {\n state.inTransaction = false;\n }\n },\n savepoint: (connection, savepointName, compileQuery) =>\n driver.savepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n rollbackToSavepoint: (connection, savepointName, compileQuery) =>\n driver.rollbackToSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseSavepoint: (connection, savepointName, compileQuery) =>\n driver.releaseSavepoint(\n getConnection(connection).connection,\n savepointName,\n compileQuery\n ),\n releaseConnection: async (connection) => {\n await driver.releaseConnection(getConnection(connection).connection);\n connections.delete(connection);\n },\n destroy: () => driver.destroy(),\n };\n }\n}\n\nexport type Kysely = K<DB>;\nexport type ControlPlaneKysely = K<ControlPlaneDB>;\nexport type ControlPlaneTransaction = T<ControlPlaneDB>;\nexport function useKysely<Database = DB>(postgres: Sql, options?: KyselyOpts) {\n console.debug('Creating Kysely instance');\n const reserveConnection = postgres.reserve.bind(postgres);\n postgres.reserve = async () => {\n const connection = await retryPostgres(\n reserveConnection,\n (error) => isRetryableConnectionError(error) || isConnectionReset(error)\n );\n if (options?.hyperdrive) {\n const unsafe = connection.unsafe;\n connection.unsafe = (query, parameters, queryOptions) =>\n unsafe(query, parameters, { ...queryOptions, prepare: true });\n }\n return connection;\n };\n const kysely = getKysely<Database>(\n new RetryingPostgresJSDialect({ postgres }),\n {\n repositoryName: options?.repositoryName,\n log: options?.log,\n }\n );\n kysely.destroy = async () => {\n console.debug('Closing Kysely connection');\n await postgres.end({ timeout: 5 }).catch(() => undefined);\n const index = _connections.indexOf(postgres);\n if (index !== -1) _connections.splice(index, 1);\n };\n\n return kysely;\n}\n\nlet _connections: postgres.Sql[] = [];\nexport async function useAsyncPostgres(connectionString: string, opt?: PgOpt) {\n const delayMs = 2500;\n const probe = opt?.probe === true;\n const retries = probe ? (opt?.retries === false ? 0 : opt?.retries || 3) : 1;\n const ssl = opt?.forceDisableSSL !== true && opt?.hyperdrive !== true;\n const url = new URL(connectionString);\n\n console.debug(\n `Creating Postgres connection with probe=${probe}, ${retries} attempts, ssl=${ssl}, and port=${url.port}`\n );\n if (_connections.length > 0)\n console.warn(`We already have ${_connections.length} Postgres connections`);\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const sql = postgres(connectionString, {\n ssl: ssl ? 'require' : false,\n target_session_attrs: 'read-write',\n // enable prepare statements, pgbouncer on crunchy allows for prepared statements\n prepare: true,\n ...(opt?.hyperdrive\n ? {\n max: 5,\n // Retire idle clients before Hyperdrive can close them asynchronously.\n idle_timeout: 10,\n }\n : {\n connect_timeout: 10,\n idle_timeout: 60,\n }),\n });\n\n if (probe) {\n await sql`select 1`;\n }\n // statement_timeout/lock_timeout are role-level settings on the cluster\n // (ALTER ROLE application SET ...) so they cover every pooled\n // connection; per-session SETs here only ever applied to one of them\n\n _connections.push(sql);\n return sql;\n } catch (err) {\n if (attempt === retries) throw err;\n console.warn(\n `Postgres connection failed (attempt ${attempt}), retrying...`\n );\n console.error('error', err);\n await new Promise((res) => setTimeout(res, delayMs));\n }\n }\n throw new KyselyError('Unable to connect to Postgres');\n}\n\nexport async function useAsyncKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return useKysely(sql, opt);\n}\n\nexport async function useAsyncControlPlaneKysely(\n connectionString: string,\n opt?: PgOpt & KyselyOpts\n) {\n const sql = await useAsyncPostgres(connectionString, opt);\n return withControlPlaneSchema(useKysely<ControlPlaneDB>(sql, opt), 'public');\n}\n\nexport async function forceCloseAllPostgres(timeoutMs = 5000) {\n await Promise.race([\n Promise.all(\n _connections.map((pg) =>\n pg.end({ timeout: timeoutMs / 1000 }).catch(() => undefined)\n )\n ),\n new Promise((res) => setTimeout(res, timeoutMs + 1000)),\n ]);\n _connections = [];\n}\n"]}
|