@proteinjs/db-driver-spanner 1.10.16 → 1.10.18
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/CHANGELOG.md +19 -0
- package/LICENSE +21 -0
- package/dist/generated/index.js +1 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/generated/test/index.js +1 -1
- package/dist/generated/test/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/SpannerDriver.d.ts +1 -0
- package/dist/src/SpannerDriver.d.ts.map +1 -1
- package/dist/src/SpannerDriver.js +4 -0
- package/dist/src/SpannerDriver.js.map +1 -1
- package/dist/src/SpannerLivenessMonitor.d.ts +20 -0
- package/dist/src/SpannerLivenessMonitor.d.ts.map +1 -0
- package/dist/src/SpannerLivenessMonitor.js +151 -0
- package/dist/src/SpannerLivenessMonitor.js.map +1 -0
- package/dist/test/Liveness.test.d.ts +2 -0
- package/dist/test/Liveness.test.d.ts.map +1 -0
- package/dist/test/Liveness.test.js +103 -0
- package/dist/test/Liveness.test.js.map +1 -0
- package/dist/test/SpannerLivenessMonitor.test.d.ts +2 -0
- package/dist/test/SpannerLivenessMonitor.test.d.ts.map +1 -0
- package/dist/test/SpannerLivenessMonitor.test.js +158 -0
- package/dist/test/SpannerLivenessMonitor.test.js.map +1 -0
- package/generated/index.ts +6 -9
- package/generated/test/index.ts +7 -10
- package/index.ts +1 -0
- package/package.json +4 -3
- package/src/SpannerDriver.ts +5 -0
- package/src/SpannerLivenessMonitor.ts +81 -0
- package/test/Liveness.test.ts +49 -0
- package/test/SpannerLivenessMonitor.test.ts +104 -0
package/generated/test/index.ts
CHANGED
|
@@ -9,11 +9,10 @@ import '@proteinjs/logger';
|
|
|
9
9
|
import '@proteinjs/reflection';
|
|
10
10
|
import '@proteinjs/util';
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
/** Generate Source Graph */
|
|
14
13
|
|
|
15
|
-
const sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/db-driver-spanner/TestDbDriverFactory\",\"value\":{\"packageName\":\"@proteinjs/db-driver-spanner\",\"name\":\"TestDbDriverFactory\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa3/packages/proteinjs/packages/db/packages/drivers/spanner/test/config/TestDbDriverFactory.ts\",\"qualifiedName\":\"@proteinjs/db-driver-spanner/TestDbDriverFactory\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[{\"name\":\"getDbDriver\",\"returnType\":{\"packageName\":\"@proteinjs/db\",\"name\":\"DbDriver\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/DbDriver\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/db\",\"name\":\"DefaultDbDriverFactory\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/DefaultDbDriverFactory\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/db/DefaultDbDriverFactory\"},{\"v\":\"@proteinjs/db-driver-spanner/SpannerDriver\",\"value\":{\"packageName\":\"@proteinjs/db-driver-spanner\",\"name\":\"SpannerDriver\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa3/packages/proteinjs/packages/db/packages/drivers/spanner/src/SpannerDriver.ts\",\"qualifiedName\":\"@proteinjs/db-driver-spanner/SpannerDriver\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"SPANNER\",\"type\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Spanner\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Spanner\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SPANNER_INSTANCE\",\"type\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Instance\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Instance\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SPANNER_DB\",\"type\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Database\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Database\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"logger\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"config\",\"type\":{\"packageName\":\"@proteinjs/db-driver-spanner\",\"name\":\"SpannerConfig\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db-driver-spanner/SpannerConfig\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"getTable\",\"type\":{\"packageName\":\"\",\"name\":\"((name: string) => Table<any>) | undefined\",\"filePath\":null,\"qualifiedName\":\"/((name: string) => Table<any>) | undefined\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"getSpanner\",\"returnType\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Spanner\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Spanner\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]},{\"name\":\"getSpannerInstance\",\"returnType\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Instance\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Instance\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]},{\"name\":\"getSpannerDb\",\"returnType\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Database\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Database\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]},{\"name\":\"getDbName\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"getTableManager\",\"returnType\":{\"packageName\":\"@proteinjs/db\",\"name\":\"TableManager\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/TableManager\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"getColumnType\",\"returnType\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"tableName\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"columnName\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"handleCaseSensitivity\",\"returnType\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"tableName\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"columnName\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"caseSensitive\",\"type\":{\"packageName\":\"\",\"name\":\"boolean\",\"filePath\":null,\"qualifiedName\":\"/boolean\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"createDbIfNotExists\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"dbExists\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<boolean>\",\"filePath\":null,\"qualifiedName\":\"/Promise<boolean>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"databaseName\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"runQuery\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<any[]>\",\"filePath\":null,\"qualifiedName\":\"/Promise<any[]>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"generateStatement\",\"type\":{\"packageName\":\"\",\"name\":\"(config: DbDriverQueryStatementConfig) => Statement\",\"filePath\":null,\"qualifiedName\":\"/(config: DbDriverQueryStatementConfig) => Statement\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"transaction\",\"type\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Transaction\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Transaction\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"executeQuery\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<any[]>\",\"filePath\":null,\"qualifiedName\":\"/Promise<any[]>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"generateStatement\",\"type\":{\"packageName\":\"\",\"name\":\"(config: DbDriverQueryStatementConfig) => Statement\",\"filePath\":null,\"qualifiedName\":\"/(config: DbDriverQueryStatementConfig) => Statement\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"runner\",\"type\":{\"packageName\":\"\",\"name\":\"Database | Transaction\",\"filePath\":null,\"qualifiedName\":\"/Database | Transaction\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"runDml\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<number>\",\"filePath\":null,\"qualifiedName\":\"/Promise<number>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"generateStatement\",\"type\":{\"packageName\":\"\",\"name\":\"(config: DbDriverDmlStatementConfig) => Statement\",\"filePath\":null,\"qualifiedName\":\"/(config: DbDriverDmlStatementConfig) => Statement\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"transaction\",\"type\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Transaction\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Transaction\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"executeDml\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<number>\",\"filePath\":null,\"qualifiedName\":\"/Promise<number>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"generateStatement\",\"type\":{\"packageName\":\"\",\"name\":\"(config: DbDriverDmlStatementConfig) => Statement\",\"filePath\":null,\"qualifiedName\":\"/(config: DbDriverDmlStatementConfig) => Statement\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"runner\",\"type\":{\"packageName\":\"@google-cloud/spanner\",\"name\":\"Transaction\",\"filePath\":null,\"qualifiedName\":\"@google-cloud/spanner/Transaction\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"runTransaction\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<T>\",\"filePath\":null,\"qualifiedName\":\"/Promise<T>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"fn\",\"type\":{\"packageName\":\"\",\"name\":\"(transaction: Transaction) => Promise<T>\",\"filePath\":null,\"qualifiedName\":\"/(transaction: Transaction) => Promise<T>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"runUpdateSchema\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"sql\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/db\",\"name\":\"DbDriver\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/DbDriver\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/db/DbDriver\"},{\"v\":\"@proteinjs/db-driver-spanner/SpannerSchemaMetadata\",\"value\":{\"packageName\":\"@proteinjs/db-driver-spanner\",\"name\":\"SpannerSchemaMetadata\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa3/packages/proteinjs/packages/db/packages/drivers/spanner/src/SpannerSchemaMetadata.ts\",\"qualifiedName\":\"@proteinjs/db-driver-spanner/SpannerSchemaMetadata\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[{\"name\":\"tableExists\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<boolean>\",\"filePath\":null,\"qualifiedName\":\"/Promise<boolean>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getColumnMetadata\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>\",\"filePath\":null,\"qualifiedName\":\"/Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getPrimaryKey\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<string[]>\",\"filePath\":null,\"qualifiedName\":\"/Promise<string[]>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getForeignKeys\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>\",\"filePath\":null,\"qualifiedName\":\"/Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getUniqueColumns\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<string[]>\",\"filePath\":null,\"qualifiedName\":\"/Promise<string[]>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getIndexes\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<{ [keyName: string]: string[] }>\",\"filePath\":null,\"qualifiedName\":\"/Promise<{ [keyName: string]: string[] }>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[{\"packageName\":\"@proteinjs/db\",\"name\":\"SchemaMetadata\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/SchemaMetadata\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[]}],\"sourceType\":2}},{\"v\":\"@proteinjs/db/SchemaMetadata\"},{\"v\":\"@proteinjs/db-driver-spanner/SpannerSchemaOperations\",\"value\":{\"packageName\":\"@proteinjs/db-driver-spanner\",\"name\":\"SpannerSchemaOperations\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa3/packages/proteinjs/packages/db/packages/drivers/spanner/src/SpannerSchemaOperations.ts\",\"qualifiedName\":\"@proteinjs/db-driver-spanner/SpannerSchemaOperations\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"logger\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"spannerDriver\",\"type\":{\"packageName\":\"@proteinjs/db-driver-spanner\",\"name\":\"SpannerDriver\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db-driver-spanner/SpannerDriver\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"}],\"methods\":[{\"name\":\"createTable\",\"returnType\":null,\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"alterTable\",\"returnType\":null,\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"tableChanges\",\"type\":{\"packageName\":\"@proteinjs/db\",\"name\":\"TableChanges\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/TableChanges\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/db\",\"name\":\"SchemaOperations\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/SchemaOperations\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/db/SchemaOperations\"}],\"edges\":[{\"v\":\"@proteinjs/db-driver-spanner/TestDbDriverFactory\",\"w\":\"@proteinjs/db/DefaultDbDriverFactory\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-driver-spanner/SpannerDriver\",\"w\":\"@proteinjs/db/DbDriver\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-driver-spanner/SpannerSchemaMetadata\",\"w\":\"@proteinjs/db/SchemaMetadata\",\"value\":\"extends class\"},{\"v\":\"@proteinjs/db-driver-spanner/SpannerSchemaOperations\",\"w\":\"@proteinjs/db/SchemaOperations\",\"value\":\"implements interface\"}]}";
|
|
16
|
-
|
|
14
|
+
const sourceGraph =
|
|
15
|
+
'{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/db-driver-spanner/TestDbDriverFactory","value":{"packageName":"@proteinjs/db-driver-spanner","name":"TestDbDriverFactory","filePath":"/home/runner/work/db/db/packages/drivers/spanner/test/config/TestDbDriverFactory.ts","qualifiedName":"@proteinjs/db-driver-spanner/TestDbDriverFactory","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[{"name":"getDbDriver","returnType":{"packageName":"@proteinjs/db","name":"DbDriver","filePath":null,"qualifiedName":"@proteinjs/db/DbDriver","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"DefaultDbDriverFactory","filePath":null,"qualifiedName":"@proteinjs/db/DefaultDbDriverFactory","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/DefaultDbDriverFactory"},{"v":"@proteinjs/db-driver-spanner/SpannerDriver","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerDriver","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerDriver.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerDriver","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"SPANNER","type":{"packageName":"@google-cloud/spanner","name":"Spanner","filePath":null,"qualifiedName":"@google-cloud/spanner/Spanner","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SPANNER_INSTANCE","type":{"packageName":"@google-cloud/spanner","name":"Instance","filePath":null,"qualifiedName":"@google-cloud/spanner/Instance","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SPANNER_DB","type":{"packageName":"@google-cloud/spanner","name":"Database","filePath":null,"qualifiedName":"@google-cloud/spanner/Database","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"LIVENESS_MONITOR","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerLivenessMonitor","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerLivenessMonitor","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"logger","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"config","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerConfig","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerConfig","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"getTable","type":{"packageName":"","name":"((name: string) => Table<any>) | undefined","filePath":null,"qualifiedName":"/((name: string) => Table<any>) | undefined","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"getSpanner","returnType":{"packageName":"@google-cloud/spanner","name":"Spanner","filePath":null,"qualifiedName":"@google-cloud/spanner/Spanner","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getSpannerInstance","returnType":{"packageName":"@google-cloud/spanner","name":"Instance","filePath":null,"qualifiedName":"@google-cloud/spanner/Instance","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getSpannerDb","returnType":{"packageName":"@google-cloud/spanner","name":"Database","filePath":null,"qualifiedName":"@google-cloud/spanner/Database","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getDbName","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"getTableManager","returnType":{"packageName":"@proteinjs/db","name":"TableManager","filePath":null,"qualifiedName":"@proteinjs/db/TableManager","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"getColumnType","returnType":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"tableName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"columnName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]},{"name":"handleCaseSensitivity","returnType":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"tableName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"columnName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"caseSensitive","type":{"packageName":"","name":"boolean","filePath":null,"qualifiedName":"/boolean","typeParameters":null,"directParents":null}}]},{"name":"createDbIfNotExists","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"dbExists","returnType":{"packageName":"","name":"Promise<boolean>","filePath":null,"qualifiedName":"/Promise<boolean>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"databaseName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]},{"name":"runQuery","returnType":{"packageName":"","name":"Promise<any[]>","filePath":null,"qualifiedName":"/Promise<any[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverQueryStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverQueryStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"executeQuery","returnType":{"packageName":"","name":"Promise<any[]>","filePath":null,"qualifiedName":"/Promise<any[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverQueryStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverQueryStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"runner","type":{"packageName":"","name":"Database | Transaction","filePath":null,"qualifiedName":"/Database | Transaction","typeParameters":null,"directParents":null}}]},{"name":"runDml","returnType":{"packageName":"","name":"Promise<number>","filePath":null,"qualifiedName":"/Promise<number>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverDmlStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverDmlStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"executeDml","returnType":{"packageName":"","name":"Promise<number>","filePath":null,"qualifiedName":"/Promise<number>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverDmlStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverDmlStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"runner","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"runTransaction","returnType":{"packageName":"","name":"Promise<T>","filePath":null,"qualifiedName":"/Promise<T>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"fn","type":{"packageName":"","name":"(transaction: Transaction) => Promise<T>","filePath":null,"qualifiedName":"/(transaction: Transaction) => Promise<T>","typeParameters":null,"directParents":null}}]},{"name":"runUpdateSchema","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"sql","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"DbDriver","filePath":null,"qualifiedName":"@proteinjs/db/DbDriver","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/DbDriver"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerSchemaMetadata","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerSchemaMetadata.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[{"name":"tableExists","returnType":{"packageName":"","name":"Promise<boolean>","filePath":null,"qualifiedName":"/Promise<boolean>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getColumnMetadata","returnType":{"packageName":"","name":"Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>","filePath":null,"qualifiedName":"/Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getPrimaryKey","returnType":{"packageName":"","name":"Promise<string[]>","filePath":null,"qualifiedName":"/Promise<string[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getForeignKeys","returnType":{"packageName":"","name":"Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>","filePath":null,"qualifiedName":"/Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getUniqueColumns","returnType":{"packageName":"","name":"Promise<string[]>","filePath":null,"qualifiedName":"/Promise<string[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getIndexes","returnType":{"packageName":"","name":"Promise<{ [keyName: string]: string[] }>","filePath":null,"qualifiedName":"/Promise<{ [keyName: string]: string[] }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"@proteinjs/db","name":"SchemaMetadata","filePath":null,"qualifiedName":"@proteinjs/db/SchemaMetadata","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}},{"v":"@proteinjs/db/SchemaMetadata"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerSchemaOperations","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerSchemaOperations.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"logger","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"spannerDriver","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerDriver","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerDriver","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"}],"methods":[{"name":"createTable","returnType":null,"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"alterTable","returnType":null,"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}},{"name":"tableChanges","type":{"packageName":"@proteinjs/db","name":"TableChanges","filePath":null,"qualifiedName":"@proteinjs/db/TableChanges","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"SchemaOperations","filePath":null,"qualifiedName":"@proteinjs/db/SchemaOperations","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/SchemaOperations"}],"edges":[{"v":"@proteinjs/db-driver-spanner/TestDbDriverFactory","w":"@proteinjs/db/DefaultDbDriverFactory","value":"implements interface"},{"v":"@proteinjs/db-driver-spanner/SpannerDriver","w":"@proteinjs/db/DbDriver","value":"implements interface"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","w":"@proteinjs/db/SchemaMetadata","value":"extends class"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","w":"@proteinjs/db/SchemaOperations","value":"implements interface"}]}';
|
|
17
16
|
|
|
18
17
|
/** Generate Source Links */
|
|
19
18
|
|
|
@@ -23,17 +22,15 @@ import { SpannerSchemaMetadata } from '../../src/SpannerSchemaMetadata';
|
|
|
23
22
|
import { SpannerSchemaOperations } from '../../src/SpannerSchemaOperations';
|
|
24
23
|
|
|
25
24
|
const sourceLinks = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
'@proteinjs/db-driver-spanner/TestDbDriverFactory': TestDbDriverFactory,
|
|
26
|
+
'@proteinjs/db-driver-spanner/SpannerDriver': SpannerDriver,
|
|
27
|
+
'@proteinjs/db-driver-spanner/SpannerSchemaMetadata': SpannerSchemaMetadata,
|
|
28
|
+
'@proteinjs/db-driver-spanner/SpannerSchemaOperations': SpannerSchemaOperations,
|
|
30
29
|
};
|
|
31
30
|
|
|
32
|
-
|
|
33
31
|
/** Load Source Graph and Links */
|
|
34
32
|
|
|
35
33
|
import { SourceRepository } from '@proteinjs/reflection';
|
|
36
34
|
SourceRepository.merge(sourceGraph, sourceLinks);
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
export * from '../../test/index';
|
|
36
|
+
export * from '../../test/index';
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proteinjs/db-driver-spanner",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.18",
|
|
4
4
|
"main": "./dist/generated/index.js",
|
|
5
5
|
"types": "./dist/generated/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@google-cloud/spanner": "7.5.0",
|
|
45
45
|
"@proteinjs/db": "^1.21.10",
|
|
46
46
|
"@proteinjs/db-query": "^1.4.8",
|
|
47
|
-
"@proteinjs/db-spanner-common": "^1.1.
|
|
47
|
+
"@proteinjs/db-spanner-common": "^1.1.32",
|
|
48
48
|
"@proteinjs/db-transaction-context": "^0.2.31",
|
|
49
49
|
"@proteinjs/logger": "^1.0.19",
|
|
50
50
|
"@proteinjs/reflection": "^1.1.11",
|
|
@@ -62,5 +62,6 @@
|
|
|
62
62
|
"jest": "29.7.0",
|
|
63
63
|
"ts-jest": "29.1.1",
|
|
64
64
|
"typescript": "5.2.2"
|
|
65
|
-
}
|
|
65
|
+
},
|
|
66
|
+
"gitHead": "45c7aba1d91005bdc11836815d10c4be5c294088"
|
|
66
67
|
}
|
package/src/SpannerDriver.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
tableByName,
|
|
9
9
|
} from '@proteinjs/db';
|
|
10
10
|
import { SpannerConfig } from './SpannerConfig';
|
|
11
|
+
import { SpannerLivenessMonitor } from './SpannerLivenessMonitor';
|
|
11
12
|
import { Logger } from '@proteinjs/logger';
|
|
12
13
|
import { Statement } from '@proteinjs/db-query';
|
|
13
14
|
import { SpannerSchemaOperations } from './SpannerSchemaOperations';
|
|
@@ -21,6 +22,7 @@ export class SpannerDriver implements DbDriver {
|
|
|
21
22
|
private static SPANNER: Spanner;
|
|
22
23
|
private static SPANNER_INSTANCE: Instance;
|
|
23
24
|
private static SPANNER_DB: Database;
|
|
25
|
+
private static LIVENESS_MONITOR: SpannerLivenessMonitor;
|
|
24
26
|
private logger = new Logger({ name: this.constructor.name });
|
|
25
27
|
private config: SpannerConfig;
|
|
26
28
|
public getTable: ((name: string) => Table<any>) | undefined;
|
|
@@ -55,6 +57,7 @@ export class SpannerDriver implements DbDriver {
|
|
|
55
57
|
private getSpannerDb(): Database {
|
|
56
58
|
if (!SpannerDriver.SPANNER_DB) {
|
|
57
59
|
SpannerDriver.SPANNER_DB = this.getSpannerInstance().database(this.config.databaseName);
|
|
60
|
+
SpannerDriver.LIVENESS_MONITOR = new SpannerLivenessMonitor(SpannerDriver.SPANNER_DB).start();
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
return SpannerDriver.SPANNER_DB;
|
|
@@ -169,6 +172,7 @@ export class SpannerDriver implements DbDriver {
|
|
|
169
172
|
message: `Failed when executing query`,
|
|
170
173
|
obj: { sql, params: namedParams, errorDetails: error.details, durationMs },
|
|
171
174
|
});
|
|
175
|
+
SpannerDriver.LIVENESS_MONITOR.reportError(error);
|
|
172
176
|
throw error;
|
|
173
177
|
}
|
|
174
178
|
}
|
|
@@ -225,6 +229,7 @@ export class SpannerDriver implements DbDriver {
|
|
|
225
229
|
message: `Failed when executing dml`,
|
|
226
230
|
obj: { sql, params: namedParams, errorDetails: error.details, durationMs },
|
|
227
231
|
});
|
|
232
|
+
SpannerDriver.LIVENESS_MONITOR.reportError(error);
|
|
228
233
|
throw error;
|
|
229
234
|
}
|
|
230
235
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Database } from '@google-cloud/spanner';
|
|
2
|
+
import { Logger } from '@proteinjs/logger';
|
|
3
|
+
|
|
4
|
+
/** grpc status codes that indicate connectivity trouble rather than an application error */
|
|
5
|
+
const CONNECTIVITY_GRPC_CODES = [4 /* DEADLINE_EXCEEDED */, 14 /* UNAVAILABLE */];
|
|
6
|
+
|
|
7
|
+
export class SpannerLivenessMonitor {
|
|
8
|
+
private static readonly PROBE_SQL = 'SELECT 1';
|
|
9
|
+
private static readonly PROBE_TIMEOUT_MS = 10_000;
|
|
10
|
+
/** delay before each attempt; 5 attempts spanning ~2 min (fast failures) to ~4.5 min (30s-deadline failures) */
|
|
11
|
+
private static readonly PROBE_DELAYS_MS = [0, 5_000, 15_000, 30_000, 60_000];
|
|
12
|
+
private logger = new Logger({ name: this.constructor.name });
|
|
13
|
+
private checkInFlight = false;
|
|
14
|
+
|
|
15
|
+
constructor(private db: Database) {}
|
|
16
|
+
|
|
17
|
+
/** Attach the single 'error' listener; called once when the Database singleton is created. */
|
|
18
|
+
start(): this {
|
|
19
|
+
this.db.on('error', (error: any) => {
|
|
20
|
+
this.logger.warn({
|
|
21
|
+
message: `Spanner session pool emitted a background error; verifying db connectivity`,
|
|
22
|
+
obj: { code: error?.code, errorDetails: error?.details ?? String(error) },
|
|
23
|
+
});
|
|
24
|
+
void this.verifyLiveness();
|
|
25
|
+
});
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Called from driver catch blocks; probes only for connectivity-shaped errors. */
|
|
30
|
+
reportError(error: any): void {
|
|
31
|
+
if (!CONNECTIVITY_GRPC_CODES.includes(error?.code)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
void this.verifyLiveness();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// --- helpers last ---
|
|
38
|
+
|
|
39
|
+
private async verifyLiveness(): Promise<void> {
|
|
40
|
+
if (this.checkInFlight) {
|
|
41
|
+
return; // coalesce: eviction sweeps emit bursts of _destroy errors (the incident evicted several sessions)
|
|
42
|
+
}
|
|
43
|
+
this.checkInFlight = true;
|
|
44
|
+
try {
|
|
45
|
+
for (let attempt = 0; attempt < SpannerLivenessMonitor.PROBE_DELAYS_MS.length; attempt++) {
|
|
46
|
+
await this.sleep(SpannerLivenessMonitor.PROBE_DELAYS_MS[attempt]);
|
|
47
|
+
try {
|
|
48
|
+
await this.probe();
|
|
49
|
+
this.logger.info({ message: `Db connectivity verified`, obj: { attempt: attempt + 1 } });
|
|
50
|
+
return;
|
|
51
|
+
} catch (error: any) {
|
|
52
|
+
this.logger.warn({
|
|
53
|
+
message: `Db connectivity probe failed`,
|
|
54
|
+
obj: { attempt: attempt + 1, errorDetails: error?.details ?? String(error) },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
this.logger.error({
|
|
59
|
+
message: `Db unreachable after sustained probing; exiting so supervision can restart into a valid state`,
|
|
60
|
+
});
|
|
61
|
+
this.exit();
|
|
62
|
+
} finally {
|
|
63
|
+
this.checkInFlight = false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private async probe(): Promise<void> {
|
|
68
|
+
await this.db.run({
|
|
69
|
+
sql: SpannerLivenessMonitor.PROBE_SQL,
|
|
70
|
+
gaxOptions: { timeout: SpannerLivenessMonitor.PROBE_TIMEOUT_MS },
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private sleep(ms: number): Promise<void> {
|
|
75
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private exit(): void {
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { Database } from '@google-cloud/spanner';
|
|
3
|
+
import { SpannerDriver, SpannerLivenessMonitor } from '@proteinjs/db-driver-spanner';
|
|
4
|
+
|
|
5
|
+
const spannerDriver = new SpannerDriver({
|
|
6
|
+
projectId: 'proteinjs-test',
|
|
7
|
+
instanceName: 'proteinjs-test',
|
|
8
|
+
databaseName: 'test',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const waitFor = async (condition: () => boolean, timeoutMs = 15_000): Promise<void> => {
|
|
12
|
+
const start = Date.now();
|
|
13
|
+
while (!condition()) {
|
|
14
|
+
if (Date.now() - start > timeoutMs) {
|
|
15
|
+
throw new Error(`Timed out after ${timeoutMs}ms waiting for condition`);
|
|
16
|
+
}
|
|
17
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe('Liveness', () => {
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
jest.restoreAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('session-pool background error does not crash the process; liveness probe runs and succeeds', async () => {
|
|
27
|
+
await spannerDriver.createDbIfNotExists();
|
|
28
|
+
const db = (spannerDriver as unknown as { getSpannerDb(): Database }).getSpannerDb();
|
|
29
|
+
const monitor = (SpannerDriver as unknown as { LIVENESS_MONITOR: SpannerLivenessMonitor }).LIVENESS_MONITOR;
|
|
30
|
+
const exitSpy = jest.spyOn(monitor as any, 'exit').mockImplementation(() => {});
|
|
31
|
+
const probeSpy = jest.spyOn(monitor as any, 'probe');
|
|
32
|
+
|
|
33
|
+
// Exercise the real library-side path: SessionPool.emit('error') is forwarded to the
|
|
34
|
+
// Database (database.js:156), which our monitor listens on. Before this fix, this emit
|
|
35
|
+
// was an unhandled 'error' event and killed the process — this test completing at all
|
|
36
|
+
// is the assertion that the crash is fixed.
|
|
37
|
+
(db as unknown as { pool_: EventEmitter }).pool_.emit(
|
|
38
|
+
'error',
|
|
39
|
+
Object.assign(new Error('4 DEADLINE_EXCEEDED: fake'), { code: 4 })
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
await waitFor(() => probeSpy.mock.calls.length > 0);
|
|
43
|
+
// the probe ran against the live emulator and must resolve
|
|
44
|
+
await probeSpy.mock.results[0].value;
|
|
45
|
+
|
|
46
|
+
expect(probeSpy).toHaveBeenCalledTimes(1);
|
|
47
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Database } from '@google-cloud/spanner';
|
|
2
|
+
import { SpannerLivenessMonitor } from '@proteinjs/db-driver-spanner';
|
|
3
|
+
|
|
4
|
+
type MonitorInternals = {
|
|
5
|
+
probe(): Promise<void>;
|
|
6
|
+
exit(): void;
|
|
7
|
+
verifyLiveness(): Promise<void>;
|
|
8
|
+
checkInFlight: boolean;
|
|
9
|
+
logger: {
|
|
10
|
+
info(args: { message: string; obj?: any }): void;
|
|
11
|
+
warn(args: { message: string; obj?: any }): void;
|
|
12
|
+
error(args: { message: string; obj?: any }): void;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** total of PROBE_DELAYS_MS [0, 5_000, 15_000, 30_000, 60_000] */
|
|
17
|
+
const ALL_PROBE_DELAYS_MS = 110_000;
|
|
18
|
+
|
|
19
|
+
describe('SpannerLivenessMonitor', () => {
|
|
20
|
+
let monitor: SpannerLivenessMonitor;
|
|
21
|
+
let internals: MonitorInternals;
|
|
22
|
+
let probeSpy: jest.SpyInstance;
|
|
23
|
+
let exitSpy: jest.SpyInstance;
|
|
24
|
+
let errorLogSpy: jest.SpyInstance;
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
jest.useFakeTimers();
|
|
28
|
+
monitor = new SpannerLivenessMonitor({} as Database);
|
|
29
|
+
internals = monitor as unknown as MonitorInternals;
|
|
30
|
+
probeSpy = jest.spyOn(monitor as any, 'probe');
|
|
31
|
+
exitSpy = jest.spyOn(monitor as any, 'exit').mockImplementation(() => {});
|
|
32
|
+
jest.spyOn(internals.logger, 'info').mockImplementation(() => {});
|
|
33
|
+
jest.spyOn(internals.logger, 'warn').mockImplementation(() => {});
|
|
34
|
+
errorLogSpy = jest.spyOn(internals.logger, 'error').mockImplementation(() => {});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
jest.useRealTimers();
|
|
39
|
+
jest.restoreAllMocks();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('first probe succeeds: no exit, checkInFlight reset', async () => {
|
|
43
|
+
probeSpy.mockResolvedValue(undefined);
|
|
44
|
+
|
|
45
|
+
const check = internals.verifyLiveness();
|
|
46
|
+
await jest.advanceTimersByTimeAsync(0);
|
|
47
|
+
await check;
|
|
48
|
+
|
|
49
|
+
expect(probeSpy).toHaveBeenCalledTimes(1);
|
|
50
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
51
|
+
expect(internals.checkInFlight).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('probe fails twice then succeeds: recovers, no exit', async () => {
|
|
55
|
+
probeSpy
|
|
56
|
+
.mockRejectedValueOnce(new Error('4 DEADLINE_EXCEEDED: fake'))
|
|
57
|
+
.mockRejectedValueOnce(new Error('4 DEADLINE_EXCEEDED: fake'))
|
|
58
|
+
.mockResolvedValue(undefined);
|
|
59
|
+
|
|
60
|
+
const check = internals.verifyLiveness();
|
|
61
|
+
await jest.advanceTimersByTimeAsync(ALL_PROBE_DELAYS_MS);
|
|
62
|
+
await check;
|
|
63
|
+
|
|
64
|
+
expect(probeSpy).toHaveBeenCalledTimes(3);
|
|
65
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
66
|
+
expect(internals.checkInFlight).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('all 5 probes fail: exit called exactly once, fatal log emitted', async () => {
|
|
70
|
+
probeSpy.mockRejectedValue(new Error('4 DEADLINE_EXCEEDED: fake'));
|
|
71
|
+
|
|
72
|
+
const check = internals.verifyLiveness();
|
|
73
|
+
await jest.advanceTimersByTimeAsync(ALL_PROBE_DELAYS_MS);
|
|
74
|
+
await check;
|
|
75
|
+
|
|
76
|
+
expect(probeSpy).toHaveBeenCalledTimes(5);
|
|
77
|
+
expect(exitSpy).toHaveBeenCalledTimes(1);
|
|
78
|
+
expect(errorLogSpy).toHaveBeenCalledWith(
|
|
79
|
+
expect.objectContaining({ message: expect.stringContaining('Db unreachable after sustained probing') })
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('burst coalescing: reportError while a check is in flight triggers one probe cycle', async () => {
|
|
84
|
+
probeSpy.mockResolvedValue(undefined);
|
|
85
|
+
|
|
86
|
+
monitor.reportError(Object.assign(new Error('4 DEADLINE_EXCEEDED: fake'), { code: 4 }));
|
|
87
|
+
monitor.reportError(Object.assign(new Error('14 UNAVAILABLE: fake'), { code: 14 }));
|
|
88
|
+
await jest.advanceTimersByTimeAsync(0);
|
|
89
|
+
|
|
90
|
+
expect(probeSpy).toHaveBeenCalledTimes(1);
|
|
91
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
92
|
+
expect(internals.checkInFlight).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('non-connectivity error code: no probe', async () => {
|
|
96
|
+
probeSpy.mockResolvedValue(undefined);
|
|
97
|
+
|
|
98
|
+
monitor.reportError(Object.assign(new Error('6 ALREADY_EXISTS: fake'), { code: 6 }));
|
|
99
|
+
await jest.advanceTimersByTimeAsync(0);
|
|
100
|
+
|
|
101
|
+
expect(probeSpy).not.toHaveBeenCalled();
|
|
102
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
103
|
+
});
|
|
104
|
+
});
|