@proteinjs/db-driver-spanner 1.15.0 → 1.16.1

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 CHANGED
@@ -3,6 +3,33 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.16.1](https://github.com/proteinjs/db/compare/@proteinjs/db-driver-spanner@1.16.0...@proteinjs/db-driver-spanner@1.16.1) (2026-08-13)
7
+
8
+
9
+ ### Performance Improvements
10
+
11
+ * preloadReferences batches loads — one IN query per referenced table ([1cf56b0](https://github.com/proteinjs/db/commit/1cf56b043c6c8078243bb829ab2d89b580476767))
12
+
13
+
14
+
15
+
16
+
17
+ # [1.16.0](https://github.com/proteinjs/db/compare/@proteinjs/db-driver-spanner@1.15.0...@proteinjs/db-driver-spanner@1.16.0) (2026-08-13)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **spanner-test:** provisioner re-ensure is zero-DDL — reconcile the retention pin instead of blind ALTER ([312427d](https://github.com/proteinjs/db/commit/312427de54856eb3d7508afa699f141f3edc1c1e))
23
+
24
+
25
+ ### Features
26
+
27
+ * composite unique indexes — Table.indexes gains unique, threaded through schema ops ([dabefd0](https://github.com/proteinjs/db/commit/dabefd07c4fc797c3d06c8c0770b7674ad33d018))
28
+
29
+
30
+
31
+
32
+
6
33
  # [1.15.0](https://github.com/proteinjs/db/compare/@proteinjs/db-driver-spanner@1.14.4...@proteinjs/db-driver-spanner@1.15.0) (2026-08-12)
7
34
 
8
35
 
@@ -51,14 +51,14 @@ var SpannerSchemaOperations = /** @class */ (function () {
51
51
  SpannerSchemaOperations.prototype.createTable = function (table) {
52
52
  var _a, _b, _c, _d;
53
53
  return __awaiter(this, void 0, void 0, function () {
54
- var indexes, _i, _e, _f, name_1, columns, serializedColumns, foreignKeys, columnPropertyName, column, columnType, createTableSql, _g, indexes_1, index, createIndexSql, indexName;
54
+ var indexes, _i, _e, _f, name_1, columns, unique, serializedColumns, foreignKeys, columnPropertyName, column, columnType, createTableSql, _g, indexes_1, index, createIndexSql, indexName;
55
55
  return __generator(this, function (_h) {
56
56
  switch (_h.label) {
57
57
  case 0:
58
58
  indexes = [];
59
59
  for (_i = 0, _e = table.indexes; _i < _e.length; _i++) {
60
- _f = _e[_i], name_1 = _f.name, columns = _f.columns;
61
- indexes.push({ name: name_1, columns: columns.map(function (x) { return table.columns[x].name; }) });
60
+ _f = _e[_i], name_1 = _f.name, columns = _f.columns, unique = _f.unique;
61
+ indexes.push({ name: name_1, columns: columns.map(function (x) { return table.columns[x].name; }), unique: unique });
62
62
  }
63
63
  serializedColumns = [];
64
64
  foreignKeys = [];
@@ -1 +1 @@
1
- {"version":3,"file":"SpannerSchemaOperations.js","sourceRoot":"","sources":["../../src/SpannerSchemaOperations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SpannerSchemaOperations.js","sourceRoot":"","sources":["../../src/SpannerSchemaOperations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import '../generated/test/index';
2
+ //# sourceMappingURL=PreloadReferences.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreloadReferences.test.d.ts","sourceRoot":"","sources":["../../test/PreloadReferences.test.ts"],"names":[],"mappings":"AAGA,OAAO,yBAAyB,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var test_1 = require("@proteinjs/db/test");
4
+ var db_driver_spanner_1 = require("@proteinjs/db-driver-spanner");
5
+ var getDropTestTable_1 = require("./util/getDropTestTable");
6
+ require("../generated/test/index");
7
+ var spannerDriver = new db_driver_spanner_1.SpannerDriver({
8
+ projectId: 'proteinjs-test',
9
+ instanceName: 'proteinjs-test',
10
+ databaseName: 'test',
11
+ });
12
+ describe('Preload References Tests', (0, test_1.preloadReferencesTests)(spannerDriver, (0, getDropTestTable_1.getDropTestTable)(spannerDriver)));
13
+ //# sourceMappingURL=PreloadReferences.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreloadReferences.test.js","sourceRoot":"","sources":["../../test/PreloadReferences.test.ts"],"names":[],"mappings":";;AAAA,2CAA4D;AAC5D,kEAA6D;AAC7D,4DAA2D;AAC3D,mCAAiC;AAEjC,IAAM,aAAa,GAAG,IAAI,iCAAa,CAAC;IACtC,SAAS,EAAE,gBAAgB;IAC3B,YAAY,EAAE,gBAAgB;IAC9B,YAAY,EAAE,MAAM;CACrB,CAAC,CAAC;AAEH,QAAQ,CAAC,0BAA0B,EAAE,IAAA,6BAAsB,EAAC,aAAa,EAAE,IAAA,mCAAgB,EAAC,aAAa,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SpannerEmulatorProvisioner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpannerEmulatorProvisioner.test.d.ts","sourceRoot":"","sources":["../../test/SpannerEmulatorProvisioner.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var spanner_1 = require("@google-cloud/spanner");
40
+ var SpannerEmulatorProvisioner_1 = require("./util/SpannerEmulatorProvisioner");
41
+ var spannerConfig = {
42
+ projectId: 'proteinjs-test',
43
+ instanceName: 'proteinjs-test',
44
+ databaseName: 'test',
45
+ };
46
+ var SCRATCH_TABLE = 'db_test_provisioner_reensure';
47
+ var retentionRows = function (database) { return __awaiter(void 0, void 0, void 0, function () {
48
+ var rows;
49
+ return __generator(this, function (_a) {
50
+ switch (_a.label) {
51
+ case 0: return [4 /*yield*/, database.run({
52
+ sql: "SELECT s.OPTION_VALUE FROM INFORMATION_SCHEMA.DATABASE_OPTIONS s WHERE s.OPTION_NAME = 'version_retention_period'",
53
+ json: true,
54
+ })];
55
+ case 1:
56
+ rows = (_a.sent())[0];
57
+ return [2 /*return*/, rows];
58
+ }
59
+ });
60
+ }); };
61
+ /**
62
+ * The provisioner's re-ensure invariant (see the class doc): `ensureProvisioned` on an
63
+ * already-provisioned, already-pinned emulator issues ZERO DDL. It runs in every fresh
64
+ * process's first beforeAll, and fresh processes appear MID-RUN (jest workerIdleMemoryLimit
65
+ * restarts) — right after a predecessor process was killed with a read-write transaction in
66
+ * flight. The emulator rejects ANY schema change while such a transaction is active, so a
67
+ * re-ensure that emits DDL fails whole suites with FAILED_PRECONDITION (the 11-suite
68
+ * flow-server CI failure, run 31643570286).
69
+ *
70
+ * The tests assert OUTCOMES against a real open read-write transaction — no mocks: a control
71
+ * leg first proves the open transaction really does reject DDL right now, so `ensureProvisioned`
72
+ * resolving in the same window proves it issued none.
73
+ */
74
+ describe('SpannerEmulatorProvisioner', function () {
75
+ var spanner = new spanner_1.Spanner({ projectId: spannerConfig.projectId });
76
+ var database;
77
+ beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
78
+ return __generator(this, function (_a) {
79
+ switch (_a.label) {
80
+ case 0:
81
+ // The run's one legitimate DDL window: on a fresh emulator this creates instance +
82
+ // database and pins retention; on a provisioned one it must reconcile without DDL.
83
+ return [4 /*yield*/, SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.ensureProvisioned(spannerConfig)];
84
+ case 1:
85
+ // The run's one legitimate DDL window: on a fresh emulator this creates instance +
86
+ // database and pins retention; on a provisioned one it must reconcile without DDL.
87
+ _a.sent();
88
+ database = spanner.instance(spannerConfig.instanceName).database(spannerConfig.databaseName);
89
+ database.on('error', function () { return undefined; });
90
+ return [2 /*return*/];
91
+ }
92
+ });
93
+ }); }, 60000);
94
+ afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
95
+ return __generator(this, function (_a) {
96
+ switch (_a.label) {
97
+ case 0: return [4 /*yield*/, database.close().catch(function () { return undefined; })];
98
+ case 1:
99
+ _a.sent();
100
+ spanner.close();
101
+ SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.release();
102
+ return [2 /*return*/];
103
+ }
104
+ });
105
+ }); }, 60000);
106
+ test('pins version_retention_period on a fresh or unpinned database', function () { return __awaiter(void 0, void 0, void 0, function () {
107
+ var rows;
108
+ return __generator(this, function (_a) {
109
+ switch (_a.label) {
110
+ case 0: return [4 /*yield*/, retentionRows(database)];
111
+ case 1:
112
+ rows = _a.sent();
113
+ expect(rows).toEqual([{ OPTION_VALUE: '1m' }]);
114
+ return [2 /*return*/];
115
+ }
116
+ });
117
+ }); }, 30000);
118
+ test('re-ensure issues zero DDL: succeeds while an open read-write transaction rejects all schema changes', function () { return __awaiter(void 0, void 0, void 0, function () {
119
+ var tables, createOp, transaction, rows;
120
+ return __generator(this, function (_a) {
121
+ switch (_a.label) {
122
+ case 0: return [4 /*yield*/, database.run({
123
+ sql: "SELECT t.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES t WHERE t.TABLE_SCHEMA = '' AND t.TABLE_NAME = '".concat(SCRATCH_TABLE, "'"),
124
+ json: true,
125
+ })];
126
+ case 1:
127
+ tables = (_a.sent())[0];
128
+ if (!(tables.length === 0)) return [3 /*break*/, 4];
129
+ return [4 /*yield*/, database.updateSchema("CREATE TABLE ".concat(SCRATCH_TABLE, " (id STRING(36)) PRIMARY KEY (id)"))];
130
+ case 2:
131
+ createOp = (_a.sent())[0];
132
+ return [4 /*yield*/, createOp.promise()];
133
+ case 3:
134
+ _a.sent();
135
+ _a.label = 4;
136
+ case 4: return [4 /*yield*/, database.getTransaction()];
137
+ case 5:
138
+ transaction = (_a.sent())[0];
139
+ _a.label = 6;
140
+ case 6:
141
+ _a.trys.push([6, , 11, 13]);
142
+ return [4 /*yield*/, transaction.runUpdate({
143
+ sql: "INSERT INTO ".concat(SCRATCH_TABLE, " (id) VALUES (@id)"),
144
+ params: { id: "re-ensure-".concat(Date.now()) },
145
+ })];
146
+ case 7:
147
+ _a.sent();
148
+ // Control leg: the open transaction really does reject DDL in this window — the same
149
+ // rejection the pre-fix unconditional pin ALTER died on. If the emulator ever stops
150
+ // rejecting schema changes under an open transaction, this control fails and flags that
151
+ // the invariant leg below has lost its bite.
152
+ return [4 /*yield*/, expect((function () { return __awaiter(void 0, void 0, void 0, function () {
153
+ var op;
154
+ return __generator(this, function (_a) {
155
+ switch (_a.label) {
156
+ case 0: return [4 /*yield*/, database.updateSchema("ALTER DATABASE `".concat(spannerConfig.databaseName, "` SET OPTIONS (version_retention_period = '1m')"))];
157
+ case 1:
158
+ op = (_a.sent())[0];
159
+ return [4 /*yield*/, op.promise()];
160
+ case 2:
161
+ _a.sent();
162
+ return [2 /*return*/];
163
+ }
164
+ });
165
+ }); })()).rejects.toMatchObject({ code: 9 /* gRPC FAILED_PRECONDITION */ })];
166
+ case 8:
167
+ // Control leg: the open transaction really does reject DDL in this window — the same
168
+ // rejection the pre-fix unconditional pin ALTER died on. If the emulator ever stops
169
+ // rejecting schema changes under an open transaction, this control fails and flags that
170
+ // the invariant leg below has lost its bite.
171
+ _a.sent();
172
+ // The invariant: re-ensure resolves inside the same window — it issued zero DDL.
173
+ return [4 /*yield*/, expect(SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.ensureProvisioned(spannerConfig)).resolves.toBeUndefined()];
174
+ case 9:
175
+ // The invariant: re-ensure resolves inside the same window — it issued zero DDL.
176
+ _a.sent();
177
+ return [4 /*yield*/, retentionRows(database)];
178
+ case 10:
179
+ rows = _a.sent();
180
+ expect(rows).toEqual([{ OPTION_VALUE: '1m' }]);
181
+ return [3 /*break*/, 13];
182
+ case 11:
183
+ // Never strand the transaction on the shared test emulator — that would poison later
184
+ // suites' DDL exactly like the class this test guards against.
185
+ return [4 /*yield*/, transaction.rollback().catch(function () { return undefined; })];
186
+ case 12:
187
+ // Never strand the transaction on the shared test emulator — that would poison later
188
+ // suites' DDL exactly like the class this test guards against.
189
+ _a.sent();
190
+ transaction.end();
191
+ return [7 /*endfinally*/];
192
+ case 13: return [2 /*return*/];
193
+ }
194
+ });
195
+ }); }, 60000);
196
+ });
197
+ //# sourceMappingURL=SpannerEmulatorProvisioner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpannerEmulatorProvisioner.test.js","sourceRoot":"","sources":["../../test/SpannerEmulatorProvisioner.test.ts"],"names":[],"mappings":"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"}
@@ -19,9 +19,23 @@
19
19
  * emulator's RSS plateaus instead of growing to OOM. Emulator-only by construction — the whole
20
20
  * path is gated on SPANNER_EMULATOR_HOST; cloud databases are never touched.
21
21
  *
22
+ * INVARIANT — re-ensuring on an already-provisioned emulator issues ZERO DDL. `ensureProvisioned`
23
+ * runs in every fresh process's first beforeAll (the once-per-run schema epoch lives on
24
+ * `process`), and fresh processes appear MID-RUN: jest's `workerIdleMemoryLimit` restarts the
25
+ * worker between suites, killing the old one with whatever background read-write transaction its
26
+ * suites left in flight. The emulator rejects ANY schema change while a read-write transaction is
27
+ * active (FAILED_PRECONDITION "a concurrent schema change operation or read-write transaction is
28
+ * already in progress"), and a transaction stranded by a killed process stays active well past the
29
+ * next suite's beforeAll — an unconditional pin ALTER here failed 11 of 101 flow-server suites in
30
+ * exactly that pattern (CI run 31643570286). Reads are immune, so the pin reconciles: read the
31
+ * current option, ALTER only on drift. The run's only legitimate DDL window stays the first
32
+ * provisioning of a fresh emulator, where no predecessor process can have stranded anything.
33
+ *
22
34
  * @internal This class is intended to be used only in tests. Do not use it in production code.
23
35
  */
24
36
  export declare class SpannerEmulatorProvisioner {
37
+ /** The retention the harness pins emulator databases to (see class doc). */
38
+ private static readonly VERSION_RETENTION_PERIOD;
25
39
  /** Kept until release(): closing right after the create-operations races their trailing LRO
26
40
  * callbacks into an unhandled "client has already been closed" that fails the suite. */
27
41
  private static client;
@@ -32,10 +46,14 @@ export declare class SpannerEmulatorProvisioner {
32
46
  databaseName: string;
33
47
  }): Promise<void>;
34
48
  /**
35
- * ALTER the emulator database's version_retention_period down to 1m (see class doc). Runs on
49
+ * Reconcile the emulator database's version_retention_period to 1m (see class doc). Runs on
36
50
  * both the fresh-create and already-exists paths — a database that survived from a previous
37
- * run must end up pinned too. Idempotent; re-pinning an already-pinned database is a no-op
38
- * option write.
51
+ * run must end up pinned too. Read-before-write, NOT a blind re-pin: the ALTER is DDL, and
52
+ * per the class invariant a re-ensure on an already-pinned database must issue zero DDL (a
53
+ * stranded read-write transaction from a killed predecessor process fails ANY schema change
54
+ * with FAILED_PRECONDITION; the read is immune). The current value comes from
55
+ * INFORMATION_SCHEMA.DATABASE_OPTIONS — the admin API's `getMetadata()` does not surface the
56
+ * option on the emulator (returns '' pinned or not; verified against emulator image 2026-08).
39
57
  */
40
58
  private static pinVersionRetention;
41
59
  /** Close the admin client — call from afterAll so jest's event loop can drain. */
@@ -1 +1 @@
1
- {"version":3,"file":"SpannerEmulatorProvisioner.d.ts","sourceRoot":"","sources":["../../../test/util/SpannerEmulatorProvisioner.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,0BAA0B;IACrC;6FACyF;IACzF,OAAO,CAAC,MAAM,CAAC,MAAM,CAAsB;IAE3C,iGAAiG;WACpF,iBAAiB,CAAC,MAAM,EAAE;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCjB;;;;;OAKG;mBACkB,mBAAmB;IAkBxC,kFAAkF;IAClF,MAAM,CAAC,OAAO,IAAI,IAAI;IAQtB,OAAO,CAAC,MAAM,CAAC,oBAAoB;CAKpC"}
1
+ {"version":3,"file":"SpannerEmulatorProvisioner.d.ts","sourceRoot":"","sources":["../../../test/util/SpannerEmulatorProvisioner.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,0BAA0B;IACrC,4EAA4E;IAC5E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAQ;IAExD;6FACyF;IACzF,OAAO,CAAC,MAAM,CAAC,MAAM,CAAsB;IAE3C,iGAAiG;WACpF,iBAAiB,CAAC,MAAM,EAAE;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCjB;;;;;;;;;OASG;mBACkB,mBAAmB;IA0BxC,kFAAkF;IAClF,MAAM,CAAC,OAAO,IAAI,IAAI;IAQtB,OAAO,CAAC,MAAM,CAAC,oBAAoB;CAKpC"}
@@ -59,6 +59,18 @@ var spanner_1 = require("@google-cloud/spanner");
59
59
  * emulator's RSS plateaus instead of growing to OOM. Emulator-only by construction — the whole
60
60
  * path is gated on SPANNER_EMULATOR_HOST; cloud databases are never touched.
61
61
  *
62
+ * INVARIANT — re-ensuring on an already-provisioned emulator issues ZERO DDL. `ensureProvisioned`
63
+ * runs in every fresh process's first beforeAll (the once-per-run schema epoch lives on
64
+ * `process`), and fresh processes appear MID-RUN: jest's `workerIdleMemoryLimit` restarts the
65
+ * worker between suites, killing the old one with whatever background read-write transaction its
66
+ * suites left in flight. The emulator rejects ANY schema change while a read-write transaction is
67
+ * active (FAILED_PRECONDITION "a concurrent schema change operation or read-write transaction is
68
+ * already in progress"), and a transaction stranded by a killed process stays active well past the
69
+ * next suite's beforeAll — an unconditional pin ALTER here failed 11 of 101 flow-server suites in
70
+ * exactly that pattern (CI run 31643570286). Reads are immune, so the pin reconciles: read the
71
+ * current option, ALTER only on drift. The run's only legitimate DDL window stays the first
72
+ * provisioning of a fresh emulator, where no predecessor process can have stranded anything.
73
+ *
62
74
  * @internal This class is intended to be used only in tests. Do not use it in production code.
63
75
  */
64
76
  var SpannerEmulatorProvisioner = /** @class */ (function () {
@@ -129,34 +141,49 @@ var SpannerEmulatorProvisioner = /** @class */ (function () {
129
141
  });
130
142
  };
131
143
  /**
132
- * ALTER the emulator database's version_retention_period down to 1m (see class doc). Runs on
144
+ * Reconcile the emulator database's version_retention_period to 1m (see class doc). Runs on
133
145
  * both the fresh-create and already-exists paths — a database that survived from a previous
134
- * run must end up pinned too. Idempotent; re-pinning an already-pinned database is a no-op
135
- * option write.
146
+ * run must end up pinned too. Read-before-write, NOT a blind re-pin: the ALTER is DDL, and
147
+ * per the class invariant a re-ensure on an already-pinned database must issue zero DDL (a
148
+ * stranded read-write transaction from a killed predecessor process fails ANY schema change
149
+ * with FAILED_PRECONDITION; the read is immune). The current value comes from
150
+ * INFORMATION_SCHEMA.DATABASE_OPTIONS — the admin API's `getMetadata()` does not surface the
151
+ * option on the emulator (returns '' pinned or not; verified against emulator image 2026-08).
136
152
  */
137
153
  SpannerEmulatorProvisioner.pinVersionRetention = function (instance, databaseName) {
154
+ var _a;
138
155
  return __awaiter(this, void 0, void 0, function () {
139
- var database, operation;
140
- return __generator(this, function (_a) {
141
- switch (_a.label) {
156
+ var database, rows, currentRetention, operation;
157
+ return __generator(this, function (_b) {
158
+ switch (_b.label) {
142
159
  case 0:
143
160
  database = instance.database(databaseName);
144
161
  database.on('error', function () { return undefined; });
145
- _a.label = 1;
162
+ _b.label = 1;
146
163
  case 1:
147
- _a.trys.push([1, , 4, 6]);
148
- return [4 /*yield*/, database.updateSchema("ALTER DATABASE `".concat(databaseName, "` SET OPTIONS (version_retention_period = '1m')"))];
164
+ _b.trys.push([1, , 5, 7]);
165
+ return [4 /*yield*/, database.run({
166
+ sql: "SELECT s.OPTION_VALUE FROM INFORMATION_SCHEMA.DATABASE_OPTIONS s WHERE s.OPTION_NAME = 'version_retention_period'",
167
+ json: true,
168
+ })];
149
169
  case 2:
150
- operation = (_a.sent())[0];
151
- return [4 /*yield*/, operation.promise()];
170
+ rows = (_b.sent())[0];
171
+ currentRetention = (_a = rows[0]) === null || _a === void 0 ? void 0 : _a.OPTION_VALUE;
172
+ if (currentRetention === SpannerEmulatorProvisioner.VERSION_RETENTION_PERIOD) {
173
+ return [2 /*return*/];
174
+ }
175
+ return [4 /*yield*/, database.updateSchema("ALTER DATABASE `".concat(databaseName, "` SET OPTIONS (version_retention_period = '").concat(SpannerEmulatorProvisioner.VERSION_RETENTION_PERIOD, "')"))];
152
176
  case 3:
153
- _a.sent();
154
- return [3 /*break*/, 6];
155
- case 4: return [4 /*yield*/, database.close().catch(function () { return undefined; })];
156
- case 5:
157
- _a.sent();
177
+ operation = (_b.sent())[0];
178
+ return [4 /*yield*/, operation.promise()];
179
+ case 4:
180
+ _b.sent();
181
+ return [3 /*break*/, 7];
182
+ case 5: return [4 /*yield*/, database.close().catch(function () { return undefined; })];
183
+ case 6:
184
+ _b.sent();
158
185
  return [7 /*endfinally*/];
159
- case 6: return [2 /*return*/];
186
+ case 7: return [2 /*return*/];
160
187
  }
161
188
  });
162
189
  });
@@ -176,6 +203,8 @@ var SpannerEmulatorProvisioner = /** @class */ (function () {
176
203
  throw error;
177
204
  }
178
205
  };
206
+ /** The retention the harness pins emulator databases to (see class doc). */
207
+ SpannerEmulatorProvisioner.VERSION_RETENTION_PERIOD = '1m';
179
208
  return SpannerEmulatorProvisioner;
180
209
  }());
181
210
  exports.SpannerEmulatorProvisioner = SpannerEmulatorProvisioner;
@@ -1 +1 @@
1
- {"version":3,"file":"SpannerEmulatorProvisioner.js","sourceRoot":"","sources":["../../../test/util/SpannerEmulatorProvisioner.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAAgD;AAEhD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAAA;IAmFA,CAAC;IA9EC,iGAAiG;IACpF,4CAAiB,GAA9B,UAA+B,MAI9B;;;;;;;wBACC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE;4BACtC,sBAAO;yBACR;wBACK,OAAO,GAAG,MAAA,0BAA0B,CAAC,MAAM,mCAAI,IAAI,iBAAO,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;wBAClG,0BAA0B,CAAC,MAAM,GAAG,OAAO,CAAC;wBACtC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;;;;wBAE/B,qBAAM,QAAQ,CAAC,MAAM,CAAC;gCAC1C,MAAM,EAAE,iBAAiB;gCACzB,WAAW,EAAE,UAAG,MAAM,CAAC,YAAY,YAAS;gCAC5C,KAAK,EAAE,CAAC;6BACT,CAAC,EAAA;;wBAJI,KAAgB,SAIpB,EAJO,SAAS,QAAA;wBAKlB,qBAAM,SAAS,CAAC,OAAO,EAAE,EAAA;;wBAAzB,SAAyB,CAAC;;;;wBAE1B,0BAA0B,CAAC,oBAAoB,CAAC,OAAK,CAAC,CAAC;;;;wBAGzB,qBAAM,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,EAAA;;wBAA1E,KAAwB,SAAkD,EAAzE,QAAQ,QAAA,EAAE,SAAS,QAAA;wBAC1B,qBAAM,SAAS,CAAC,OAAO,EAAE,EAAA;;wBAAzB,SAAyB,CAAC;wBAC1B,0FAA0F;wBAC1F,2FAA2F;wBAC3F,0FAA0F;wBAC1F,yFAAyF;wBACzF,2FAA2F;wBAC3F,wFAAwF;wBACxF,4EAA4E;wBAC5E,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC,CAAC;wBACtC,qBAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC,EAAA;;wBAA7C,SAA6C,CAAC;;;;wBAE9C,0BAA0B,CAAC,oBAAoB,CAAC,OAAK,CAAC,CAAC;;6BAEzD,qBAAM,0BAA0B,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,YAAY,CAAC,EAAA;;wBAAnF,SAAmF,CAAC;;;;;KACrF;IAED;;;;;OAKG;IACkB,8CAAmB,GAAxC,UACE,QAAyC,EACzC,YAAoB;;;;;;wBAId,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;wBACjD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC,CAAC;;;;wBAEhB,qBAAM,QAAQ,CAAC,YAAY,CAC7C,0BAAoB,YAAY,oDAAkD,CACnF,EAAA;;wBAFM,SAAS,GAAI,CAAA,SAEnB,CAAA,GAFe;wBAGhB,qBAAM,SAAS,CAAC,OAAO,EAAE,EAAA;;wBAAzB,SAAyB,CAAC;;4BAE1B,qBAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC,EAAA;;wBAA7C,SAA6C,CAAC;;;;;;KAEjD;IAED,kFAAkF;IAC3E,kCAAO,GAAd;;QACE,IAAI;YACF,MAAA,0BAA0B,CAAC,MAAM,0CAAE,KAAK,EAAE,CAAC;SAC5C;gBAAS;YACR,0BAA0B,CAAC,MAAM,GAAG,SAAS,CAAC;SAC/C;IACH,CAAC;IAEc,+CAAoB,GAAnC,UAAoC,KAAc;QAChD,IAAK,KAA2B,CAAC,IAAI,KAAK,CAAC,CAAC,yBAAyB,EAAE;YACrE,MAAM,KAAK,CAAC;SACb;IACH,CAAC;IACH,iCAAC;AAAD,CAAC,AAnFD,IAmFC;AAnFY,gEAA0B"}
1
+ {"version":3,"file":"SpannerEmulatorProvisioner.js","sourceRoot":"","sources":["../../../test/util/SpannerEmulatorProvisioner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/db-driver-spanner",
3
- "version": "1.15.0",
3
+ "version": "1.16.1",
4
4
  "main": "./dist/generated/index.js",
5
5
  "types": "./dist/generated/index.d.ts",
6
6
  "exports": {
@@ -42,10 +42,10 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@google-cloud/spanner": "7.5.0",
45
- "@proteinjs/db": "^1.28.1",
45
+ "@proteinjs/db": "^1.29.1",
46
46
  "@proteinjs/db-query": "^1.6.0",
47
- "@proteinjs/db-spanner-common": "^1.3.1",
48
- "@proteinjs/db-transaction-context": "^0.5.1",
47
+ "@proteinjs/db-spanner-common": "^1.3.3",
48
+ "@proteinjs/db-transaction-context": "^0.5.3",
49
49
  "@proteinjs/logger": "^1.0.21",
50
50
  "@proteinjs/reflection": "^1.1.12",
51
51
  "@proteinjs/util": "^1.6.1"
@@ -63,5 +63,5 @@
63
63
  "ts-jest": "29.1.1",
64
64
  "typescript": "5.2.2"
65
65
  },
66
- "gitHead": "f9897c1acec281720cd39926756ab7aa866baa5b"
66
+ "gitHead": "c945fb49ea7db32eb5bf51630eff23f5df06560c"
67
67
  }
@@ -20,8 +20,8 @@ export class SpannerSchemaOperations implements SchemaOperations {
20
20
 
21
21
  async createTable(table: Table<any>) {
22
22
  const indexes: { name?: string; columns: string[]; unique?: boolean }[] = [];
23
- for (const { name, columns } of table.indexes) {
24
- indexes.push({ name, columns: columns.map((x) => table.columns[x as string]!.name) });
23
+ for (const { name, columns, unique } of table.indexes) {
24
+ indexes.push({ name, columns: columns.map((x) => table.columns[x as string]!.name), unique });
25
25
  }
26
26
 
27
27
  const serializedColumns: { name: string; type: string; nullable?: boolean }[] = [];
@@ -0,0 +1,12 @@
1
+ import { preloadReferencesTests } from '@proteinjs/db/test';
2
+ import { SpannerDriver } from '@proteinjs/db-driver-spanner';
3
+ import { getDropTestTable } from './util/getDropTestTable';
4
+ import '../generated/test/index';
5
+
6
+ const spannerDriver = new SpannerDriver({
7
+ projectId: 'proteinjs-test',
8
+ instanceName: 'proteinjs-test',
9
+ databaseName: 'test',
10
+ });
11
+
12
+ describe('Preload References Tests', preloadReferencesTests(spannerDriver, getDropTestTable(spannerDriver)));
@@ -0,0 +1,105 @@
1
+ import { Spanner, Database, Transaction } from '@google-cloud/spanner';
2
+ import { SpannerEmulatorProvisioner } from './util/SpannerEmulatorProvisioner';
3
+
4
+ const spannerConfig = {
5
+ projectId: 'proteinjs-test',
6
+ instanceName: 'proteinjs-test',
7
+ databaseName: 'test',
8
+ };
9
+
10
+ const SCRATCH_TABLE = 'db_test_provisioner_reensure';
11
+
12
+ const retentionRows = async (database: Database) => {
13
+ const [rows] = await database.run({
14
+ sql: `SELECT s.OPTION_VALUE FROM INFORMATION_SCHEMA.DATABASE_OPTIONS s WHERE s.OPTION_NAME = 'version_retention_period'`,
15
+ json: true,
16
+ });
17
+ return rows as { OPTION_VALUE: string }[];
18
+ };
19
+
20
+ /**
21
+ * The provisioner's re-ensure invariant (see the class doc): `ensureProvisioned` on an
22
+ * already-provisioned, already-pinned emulator issues ZERO DDL. It runs in every fresh
23
+ * process's first beforeAll, and fresh processes appear MID-RUN (jest workerIdleMemoryLimit
24
+ * restarts) — right after a predecessor process was killed with a read-write transaction in
25
+ * flight. The emulator rejects ANY schema change while such a transaction is active, so a
26
+ * re-ensure that emits DDL fails whole suites with FAILED_PRECONDITION (the 11-suite
27
+ * flow-server CI failure, run 31643570286).
28
+ *
29
+ * The tests assert OUTCOMES against a real open read-write transaction — no mocks: a control
30
+ * leg first proves the open transaction really does reject DDL right now, so `ensureProvisioned`
31
+ * resolving in the same window proves it issued none.
32
+ */
33
+ describe('SpannerEmulatorProvisioner', () => {
34
+ const spanner = new Spanner({ projectId: spannerConfig.projectId });
35
+ let database: Database;
36
+
37
+ beforeAll(async () => {
38
+ // The run's one legitimate DDL window: on a fresh emulator this creates instance +
39
+ // database and pins retention; on a provisioned one it must reconcile without DDL.
40
+ await SpannerEmulatorProvisioner.ensureProvisioned(spannerConfig);
41
+ database = spanner.instance(spannerConfig.instanceName).database(spannerConfig.databaseName);
42
+ database.on('error', () => undefined);
43
+ }, 60_000);
44
+
45
+ afterAll(async () => {
46
+ await database.close().catch(() => undefined);
47
+ spanner.close();
48
+ SpannerEmulatorProvisioner.release();
49
+ }, 60_000);
50
+
51
+ test('pins version_retention_period on a fresh or unpinned database', async () => {
52
+ // Outcome of the beforeAll ensure: the option is present and pinned. Guards the skip
53
+ // condition from ever decaying into never-pinning.
54
+ const rows = await retentionRows(database);
55
+ expect(rows).toEqual([{ OPTION_VALUE: '1m' }]);
56
+ }, 30_000);
57
+
58
+ test('re-ensure issues zero DDL: succeeds while an open read-write transaction rejects all schema changes', async () => {
59
+ // Scratch table for the transaction's uncommitted write — created BEFORE the transaction
60
+ // opens (DDL is legal here), only when a previous run didn't leave it behind.
61
+ const [tables] = await database.run({
62
+ sql: `SELECT t.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES t WHERE t.TABLE_SCHEMA = '' AND t.TABLE_NAME = '${SCRATCH_TABLE}'`,
63
+ json: true,
64
+ });
65
+ if (tables.length === 0) {
66
+ const [createOp] = await database.updateSchema(`CREATE TABLE ${SCRATCH_TABLE} (id STRING(36)) PRIMARY KEY (id)`);
67
+ await createOp.promise();
68
+ }
69
+
70
+ // Model the stranded transaction a killed jest worker leaves behind: a read-write
71
+ // transaction with real uncommitted work, held open across the re-ensure.
72
+ const [transaction] = (await database.getTransaction()) as unknown as [Transaction];
73
+ try {
74
+ await transaction.runUpdate({
75
+ sql: `INSERT INTO ${SCRATCH_TABLE} (id) VALUES (@id)`,
76
+ params: { id: `re-ensure-${Date.now()}` },
77
+ });
78
+
79
+ // Control leg: the open transaction really does reject DDL in this window — the same
80
+ // rejection the pre-fix unconditional pin ALTER died on. If the emulator ever stops
81
+ // rejecting schema changes under an open transaction, this control fails and flags that
82
+ // the invariant leg below has lost its bite.
83
+ await expect(
84
+ (async () => {
85
+ const [op] = await database.updateSchema(
86
+ `ALTER DATABASE \`${spannerConfig.databaseName}\` SET OPTIONS (version_retention_period = '1m')`
87
+ );
88
+ await op.promise();
89
+ })()
90
+ ).rejects.toMatchObject({ code: 9 /* gRPC FAILED_PRECONDITION */ });
91
+
92
+ // The invariant: re-ensure resolves inside the same window — it issued zero DDL.
93
+ await expect(SpannerEmulatorProvisioner.ensureProvisioned(spannerConfig)).resolves.toBeUndefined();
94
+
95
+ // And it reconciled rather than skipped: retention still reads pinned.
96
+ const rows = await retentionRows(database);
97
+ expect(rows).toEqual([{ OPTION_VALUE: '1m' }]);
98
+ } finally {
99
+ // Never strand the transaction on the shared test emulator — that would poison later
100
+ // suites' DDL exactly like the class this test guards against.
101
+ await transaction.rollback().catch(() => undefined);
102
+ transaction.end();
103
+ }
104
+ }, 60_000);
105
+ });
@@ -21,9 +21,24 @@ import { Spanner } from '@google-cloud/spanner';
21
21
  * emulator's RSS plateaus instead of growing to OOM. Emulator-only by construction — the whole
22
22
  * path is gated on SPANNER_EMULATOR_HOST; cloud databases are never touched.
23
23
  *
24
+ * INVARIANT — re-ensuring on an already-provisioned emulator issues ZERO DDL. `ensureProvisioned`
25
+ * runs in every fresh process's first beforeAll (the once-per-run schema epoch lives on
26
+ * `process`), and fresh processes appear MID-RUN: jest's `workerIdleMemoryLimit` restarts the
27
+ * worker between suites, killing the old one with whatever background read-write transaction its
28
+ * suites left in flight. The emulator rejects ANY schema change while a read-write transaction is
29
+ * active (FAILED_PRECONDITION "a concurrent schema change operation or read-write transaction is
30
+ * already in progress"), and a transaction stranded by a killed process stays active well past the
31
+ * next suite's beforeAll — an unconditional pin ALTER here failed 11 of 101 flow-server suites in
32
+ * exactly that pattern (CI run 31643570286). Reads are immune, so the pin reconciles: read the
33
+ * current option, ALTER only on drift. The run's only legitimate DDL window stays the first
34
+ * provisioning of a fresh emulator, where no predecessor process can have stranded anything.
35
+ *
24
36
  * @internal This class is intended to be used only in tests. Do not use it in production code.
25
37
  */
26
38
  export class SpannerEmulatorProvisioner {
39
+ /** The retention the harness pins emulator databases to (see class doc). */
40
+ private static readonly VERSION_RETENTION_PERIOD = '1m';
41
+
27
42
  /** Kept until release(): closing right after the create-operations races their trailing LRO
28
43
  * callbacks into an unhandled "client has already been closed" that fails the suite. */
29
44
  private static client: Spanner | undefined;
@@ -69,10 +84,14 @@ export class SpannerEmulatorProvisioner {
69
84
  }
70
85
 
71
86
  /**
72
- * ALTER the emulator database's version_retention_period down to 1m (see class doc). Runs on
87
+ * Reconcile the emulator database's version_retention_period to 1m (see class doc). Runs on
73
88
  * both the fresh-create and already-exists paths — a database that survived from a previous
74
- * run must end up pinned too. Idempotent; re-pinning an already-pinned database is a no-op
75
- * option write.
89
+ * run must end up pinned too. Read-before-write, NOT a blind re-pin: the ALTER is DDL, and
90
+ * per the class invariant a re-ensure on an already-pinned database must issue zero DDL (a
91
+ * stranded read-write transaction from a killed predecessor process fails ANY schema change
92
+ * with FAILED_PRECONDITION; the read is immune). The current value comes from
93
+ * INFORMATION_SCHEMA.DATABASE_OPTIONS — the admin API's `getMetadata()` does not surface the
94
+ * option on the emulator (returns '' pinned or not; verified against emulator image 2026-08).
76
95
  */
77
96
  private static async pinVersionRetention(
78
97
  instance: ReturnType<Spanner['instance']>,
@@ -83,8 +102,16 @@ export class SpannerEmulatorProvisioner {
83
102
  const database = instance.database(databaseName);
84
103
  database.on('error', () => undefined);
85
104
  try {
105
+ const [rows] = await database.run({
106
+ sql: `SELECT s.OPTION_VALUE FROM INFORMATION_SCHEMA.DATABASE_OPTIONS s WHERE s.OPTION_NAME = 'version_retention_period'`,
107
+ json: true,
108
+ });
109
+ const currentRetention = (rows[0] as { OPTION_VALUE?: string } | undefined)?.OPTION_VALUE;
110
+ if (currentRetention === SpannerEmulatorProvisioner.VERSION_RETENTION_PERIOD) {
111
+ return;
112
+ }
86
113
  const [operation] = await database.updateSchema(
87
- `ALTER DATABASE \`${databaseName}\` SET OPTIONS (version_retention_period = '1m')`
114
+ `ALTER DATABASE \`${databaseName}\` SET OPTIONS (version_retention_period = '${SpannerEmulatorProvisioner.VERSION_RETENTION_PERIOD}')`
88
115
  );
89
116
  await operation.promise();
90
117
  } finally {