@proteinjs/db-driver-spanner 1.12.3 → 1.14.0
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 +13 -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.d.ts.map +1 -1
- package/dist/generated/test/index.js +3 -1
- package/dist/generated/test/index.js.map +1 -1
- package/dist/src/SpannerConfig.d.ts +22 -0
- package/dist/src/SpannerConfig.d.ts.map +1 -1
- package/dist/src/SpannerDriver.d.ts +56 -9
- package/dist/src/SpannerDriver.d.ts.map +1 -1
- package/dist/src/SpannerDriver.js +229 -35
- package/dist/src/SpannerDriver.js.map +1 -1
- package/dist/src/SpannerLivenessMonitor.d.ts +25 -0
- package/dist/src/SpannerLivenessMonitor.d.ts.map +1 -1
- package/dist/src/SpannerLivenessMonitor.js +59 -4
- package/dist/src/SpannerLivenessMonitor.js.map +1 -1
- package/dist/test/ServiceUpdateVerbs.test.d.ts +2 -0
- package/dist/test/ServiceUpdateVerbs.test.d.ts.map +1 -0
- package/dist/test/ServiceUpdateVerbs.test.js +325 -0
- package/dist/test/ServiceUpdateVerbs.test.js.map +1 -0
- package/dist/test/SessionPoolExhaustion.test.d.ts +2 -0
- package/dist/test/SessionPoolExhaustion.test.d.ts.map +1 -0
- package/dist/test/SessionPoolExhaustion.test.js +230 -0
- package/dist/test/SessionPoolExhaustion.test.js.map +1 -0
- package/dist/test/SessionRecordTableQuery.test.d.ts +2 -0
- package/dist/test/SessionRecordTableQuery.test.d.ts.map +1 -0
- package/dist/test/SessionRecordTableQuery.test.js +185 -0
- package/dist/test/SessionRecordTableQuery.test.js.map +1 -0
- package/dist/test/SpannerLivenessMonitor.test.js +65 -0
- package/dist/test/SpannerLivenessMonitor.test.js.map +1 -1
- package/dist/test/SpannerOperationDeadline.test.d.ts +2 -0
- package/dist/test/SpannerOperationDeadline.test.d.ts.map +1 -0
- package/dist/test/SpannerOperationDeadline.test.js +227 -0
- package/dist/test/SpannerOperationDeadline.test.js.map +1 -0
- package/dist/test/TransactionSafety.test.d.ts +2 -0
- package/dist/test/TransactionSafety.test.d.ts.map +1 -0
- package/dist/test/TransactionSafety.test.js +325 -0
- package/dist/test/TransactionSafety.test.js.map +1 -0
- package/dist/test/index.d.ts +1 -0
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +1 -0
- package/dist/test/index.js.map +1 -1
- package/dist/test/util/serviceUpdateVerbsTestTables.d.ts +45 -0
- package/dist/test/util/serviceUpdateVerbsTestTables.d.ts.map +1 -0
- package/dist/test/util/serviceUpdateVerbsTestTables.js +100 -0
- package/dist/test/util/serviceUpdateVerbsTestTables.js.map +1 -0
- package/generated/index.ts +6 -9
- package/generated/test/index.ts +9 -10
- package/package.json +7 -6
- package/src/SpannerConfig.ts +22 -0
- package/src/SpannerDriver.ts +215 -28
- package/src/SpannerLivenessMonitor.ts +73 -5
- package/test/ServiceUpdateVerbs.test.ts +188 -0
- package/test/SessionPoolExhaustion.test.ts +127 -0
- package/test/SessionRecordTableQuery.test.ts +118 -0
- package/test/SpannerLivenessMonitor.test.ts +70 -0
- package/test/SpannerOperationDeadline.test.ts +156 -0
- package/test/TransactionSafety.test.ts +157 -0
- package/test/index.ts +1 -0
- package/test/util/serviceUpdateVerbsTestTables.ts +55 -0
|
@@ -0,0 +1,325 @@
|
|
|
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
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
39
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
40
|
+
if (ar || !(i in from)) {
|
|
41
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
42
|
+
ar[i] = from[i];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
var db_driver_spanner_1 = require("@proteinjs/db-driver-spanner");
|
|
49
|
+
var db_1 = require("@proteinjs/db");
|
|
50
|
+
var db_transaction_context_1 = require("@proteinjs/db-transaction-context");
|
|
51
|
+
var getDropTestTable_1 = require("./util/getDropTestTable");
|
|
52
|
+
var SpannerEmulatorProvisioner_1 = require("./util/SpannerEmulatorProvisioner");
|
|
53
|
+
var serviceUpdateVerbsTestTables_1 = require("./util/serviceUpdateVerbsTestTables");
|
|
54
|
+
require("../generated/test/index");
|
|
55
|
+
/**
|
|
56
|
+
* The RMW update verbs (`updateArrayMembership`, `updatePreserving`) over the DbService RPC
|
|
57
|
+
* path, against real Spanner transaction semantics.
|
|
58
|
+
*
|
|
59
|
+
* The service path differs from bespoke server code in three load-bearing ways, each pinned here:
|
|
60
|
+
* - ONE long-lived `Db` instance serves every request (ServiceRouter builds its executor map
|
|
61
|
+
* once), so the verbs' self-wrapped transactions must not couple concurrent callers through
|
|
62
|
+
* instance state.
|
|
63
|
+
* - args cross a serialization boundary: `Table` as `{ tableName }` resolved via `tableByName`,
|
|
64
|
+
* the op payloads (`ArrayMembershipUpdate`, `PreservedPath`) as plain JSON.
|
|
65
|
+
* - authorization is the `TableServiceAuth.canAccess(methodName, args)` gate plus scoped/column
|
|
66
|
+
* query injection inside the verb's read-modify-write — an out-of-scope row must behave as
|
|
67
|
+
* nonexistent.
|
|
68
|
+
*/
|
|
69
|
+
var spannerDriver = new db_driver_spanner_1.SpannerDriver({
|
|
70
|
+
projectId: 'proteinjs-test',
|
|
71
|
+
instanceName: 'proteinjs-test',
|
|
72
|
+
databaseName: 'test',
|
|
73
|
+
});
|
|
74
|
+
describe('DbService RMW update verbs (updateArrayMembership / updatePreserving)', function () {
|
|
75
|
+
var docTable = new serviceUpdateVerbsTestTables_1.ServiceVerbsDocTable();
|
|
76
|
+
var dropTable = (0, getDropTestTable_1.getDropTestTable)(spannerDriver);
|
|
77
|
+
// Service-singleton shaped: one shared instance, default table resolution (tableByName).
|
|
78
|
+
var db = new db_1.Db(spannerDriver, undefined, new db_transaction_context_1.TransactionContext());
|
|
79
|
+
/**
|
|
80
|
+
* The wire forms the Serializer produces for DbService args: `Table` crosses as its name and is
|
|
81
|
+
* resolved via `tableByName` server-side (TableSerializer); the op payloads are plain JSON.
|
|
82
|
+
*/
|
|
83
|
+
var overWire = function (args) {
|
|
84
|
+
return args.map(function (arg) { return ((0, db_1.isTable)(arg) ? (0, db_1.tableByName)(arg.name) : JSON.parse(JSON.stringify(arg))); });
|
|
85
|
+
};
|
|
86
|
+
/** Invoke like ServiceExecutor does: deserialize wire args, run the canAccess gate, call the method. */
|
|
87
|
+
var rpc = function (methodName, args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
88
|
+
var wireArgs;
|
|
89
|
+
var _a;
|
|
90
|
+
return __generator(this, function (_b) {
|
|
91
|
+
switch (_b.label) {
|
|
92
|
+
case 0:
|
|
93
|
+
wireArgs = overWire(args);
|
|
94
|
+
if (!db.serviceMetadata.auth.canAccess(methodName, wireArgs)) {
|
|
95
|
+
throw new Error("User not authorized to run service: DbService.".concat(methodName));
|
|
96
|
+
}
|
|
97
|
+
return [4 /*yield*/, (_a = db)[methodName].apply(_a, wireArgs)];
|
|
98
|
+
case 1: return [2 /*return*/, _b.sent()];
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}); };
|
|
102
|
+
var memberIds = function (id) { return __awaiter(void 0, void 0, void 0, function () {
|
|
103
|
+
var row;
|
|
104
|
+
var _a;
|
|
105
|
+
return __generator(this, function (_b) {
|
|
106
|
+
switch (_b.label) {
|
|
107
|
+
case 0: return [4 /*yield*/, db.get(docTable, { id: id })];
|
|
108
|
+
case 1:
|
|
109
|
+
row = _b.sent();
|
|
110
|
+
return [2 /*return*/, (_a = row === null || row === void 0 ? void 0 : row.members) === null || _a === void 0 ? void 0 : _a._ids];
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}); };
|
|
114
|
+
beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
115
|
+
return __generator(this, function (_a) {
|
|
116
|
+
switch (_a.label) {
|
|
117
|
+
case 0: return [4 /*yield*/, SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.ensureProvisioned({
|
|
118
|
+
projectId: 'proteinjs-test',
|
|
119
|
+
instanceName: 'proteinjs-test',
|
|
120
|
+
databaseName: 'test',
|
|
121
|
+
})];
|
|
122
|
+
case 1:
|
|
123
|
+
_a.sent();
|
|
124
|
+
return [4 /*yield*/, dropTable(docTable)];
|
|
125
|
+
case 2:
|
|
126
|
+
_a.sent();
|
|
127
|
+
return [4 /*yield*/, spannerDriver.getTableManager().loadTable(docTable)];
|
|
128
|
+
case 3:
|
|
129
|
+
_a.sent();
|
|
130
|
+
return [2 /*return*/];
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}); }, 60000);
|
|
134
|
+
afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
135
|
+
return __generator(this, function (_a) {
|
|
136
|
+
switch (_a.label) {
|
|
137
|
+
case 0: return [4 /*yield*/, dropTable(docTable)];
|
|
138
|
+
case 1:
|
|
139
|
+
_a.sent();
|
|
140
|
+
return [4 /*yield*/, SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.release()];
|
|
141
|
+
case 2:
|
|
142
|
+
_a.sent();
|
|
143
|
+
return [2 /*return*/];
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}); }, 30000);
|
|
147
|
+
beforeEach(function () {
|
|
148
|
+
serviceUpdateVerbsTestTables_1.serviceVerbsScopeContext.current = 'scope-a';
|
|
149
|
+
});
|
|
150
|
+
test('membership ops apply against committed truth, not the caller list snapshot', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
151
|
+
var doc, update, _a, _b;
|
|
152
|
+
return __generator(this, function (_c) {
|
|
153
|
+
switch (_c.label) {
|
|
154
|
+
case 0: return [4 /*yield*/, db.insert(docTable, {
|
|
155
|
+
title: 'd1',
|
|
156
|
+
members: new db_1.ReferenceArray(docTable.name, ['a', 'b', 'c']),
|
|
157
|
+
})];
|
|
158
|
+
case 1:
|
|
159
|
+
doc = _c.sent();
|
|
160
|
+
// Another writer's committed wholesale update adds `d` — the caller's snapshot is now stale.
|
|
161
|
+
return [4 /*yield*/, db.update(docTable, { id: doc.id, members: new db_1.ReferenceArray(docTable.name, ['a', 'b', 'c', 'd']) })];
|
|
162
|
+
case 2:
|
|
163
|
+
// Another writer's committed wholesale update adds `d` — the caller's snapshot is now stale.
|
|
164
|
+
_c.sent();
|
|
165
|
+
update = {
|
|
166
|
+
recordId: doc.id,
|
|
167
|
+
columnPropertyName: 'members',
|
|
168
|
+
ops: (0, db_1.computeArrayMembershipOps)(['a', 'b', 'c'], ['a', 'c']),
|
|
169
|
+
};
|
|
170
|
+
_a = expect;
|
|
171
|
+
return [4 /*yield*/, rpc('updateArrayMembership', [docTable, update])];
|
|
172
|
+
case 3:
|
|
173
|
+
_a.apply(void 0, [_c.sent()]).toBe(1);
|
|
174
|
+
// Both writers' effects survive; a wholesale write of the stale list would have erased `d`.
|
|
175
|
+
_b = expect;
|
|
176
|
+
return [4 /*yield*/, memberIds(doc.id)];
|
|
177
|
+
case 4:
|
|
178
|
+
// Both writers' effects survive; a wholesale write of the stale list would have erased `d`.
|
|
179
|
+
_b.apply(void 0, [_c.sent()]).toEqual(['a', 'c', 'd']);
|
|
180
|
+
return [2 /*return*/];
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}); });
|
|
184
|
+
test('a scoped caller cannot touch another scope’s row via updateArrayMembership', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
185
|
+
var doc, removeA, _a, _b, _c, _d;
|
|
186
|
+
return __generator(this, function (_e) {
|
|
187
|
+
switch (_e.label) {
|
|
188
|
+
case 0: return [4 /*yield*/, db.insert(docTable, { title: 'd2', members: new db_1.ReferenceArray(docTable.name, ['a', 'b']) })];
|
|
189
|
+
case 1:
|
|
190
|
+
doc = _e.sent();
|
|
191
|
+
serviceUpdateVerbsTestTables_1.serviceVerbsScopeContext.current = 'scope-b';
|
|
192
|
+
removeA = {
|
|
193
|
+
recordId: doc.id,
|
|
194
|
+
columnPropertyName: 'members',
|
|
195
|
+
ops: [{ op: 'remove', id: 'a' }],
|
|
196
|
+
};
|
|
197
|
+
_a = expect;
|
|
198
|
+
return [4 /*yield*/, rpc('updateArrayMembership', [docTable, removeA])];
|
|
199
|
+
case 2:
|
|
200
|
+
_a.apply(void 0, [_e.sent()]).toBe(0);
|
|
201
|
+
serviceUpdateVerbsTestTables_1.serviceVerbsScopeContext.current = 'scope-a';
|
|
202
|
+
_b = expect;
|
|
203
|
+
return [4 /*yield*/, memberIds(doc.id)];
|
|
204
|
+
case 3:
|
|
205
|
+
_b.apply(void 0, [_e.sent()]).toEqual(['a', 'b']);
|
|
206
|
+
// The owning scope can perform the identical op.
|
|
207
|
+
_c = expect;
|
|
208
|
+
return [4 /*yield*/, rpc('updateArrayMembership', [docTable, removeA])];
|
|
209
|
+
case 4:
|
|
210
|
+
// The owning scope can perform the identical op.
|
|
211
|
+
_c.apply(void 0, [_e.sent()]).toBe(1);
|
|
212
|
+
_d = expect;
|
|
213
|
+
return [4 /*yield*/, memberIds(doc.id)];
|
|
214
|
+
case 5:
|
|
215
|
+
_d.apply(void 0, [_e.sent()]).toEqual(['b']);
|
|
216
|
+
return [2 /*return*/];
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}); });
|
|
220
|
+
test('a scoped caller cannot touch another scope’s row via updatePreserving', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
221
|
+
var doc, preserve, foreignWrite, _a, row;
|
|
222
|
+
return __generator(this, function (_b) {
|
|
223
|
+
switch (_b.label) {
|
|
224
|
+
case 0: return [4 /*yield*/, db.insert(docTable, { title: 'd3', body: { content: 'v1', style: { color: 'blue' } } })];
|
|
225
|
+
case 1:
|
|
226
|
+
doc = _b.sent();
|
|
227
|
+
serviceUpdateVerbsTestTables_1.serviceVerbsScopeContext.current = 'scope-b';
|
|
228
|
+
preserve = [{ columnPropertyName: 'body', paths: ['content'], whenType: 'string' }];
|
|
229
|
+
foreignWrite = { id: doc.id, body: { content: 'hijack', style: { color: 'red' } } };
|
|
230
|
+
_a = expect;
|
|
231
|
+
return [4 /*yield*/, rpc('updatePreserving', [docTable, foreignWrite, preserve])];
|
|
232
|
+
case 2:
|
|
233
|
+
_a.apply(void 0, [_b.sent()]).toBe(0);
|
|
234
|
+
serviceUpdateVerbsTestTables_1.serviceVerbsScopeContext.current = 'scope-a';
|
|
235
|
+
return [4 /*yield*/, db.get(docTable, { id: doc.id })];
|
|
236
|
+
case 3:
|
|
237
|
+
row = _b.sent();
|
|
238
|
+
expect(row.body).toEqual({ content: 'v1', style: { color: 'blue' } });
|
|
239
|
+
return [2 /*return*/];
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}); });
|
|
243
|
+
test('updatePreserving over the service preserves the committed sub-path while writing owned paths', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
244
|
+
var doc, preserve, stalePayload, _a, row;
|
|
245
|
+
return __generator(this, function (_b) {
|
|
246
|
+
switch (_b.label) {
|
|
247
|
+
case 0: return [4 /*yield*/, db.insert(docTable, { title: 'd4', body: { content: 'v1', style: { color: 'blue' } } })];
|
|
248
|
+
case 1:
|
|
249
|
+
doc = _b.sent();
|
|
250
|
+
// The owning writer's committed text save; the structural writer's payload still carries v1.
|
|
251
|
+
return [4 /*yield*/, db.update(docTable, { id: doc.id, body: { content: 'v2', style: { color: 'blue' } } })];
|
|
252
|
+
case 2:
|
|
253
|
+
// The owning writer's committed text save; the structural writer's payload still carries v1.
|
|
254
|
+
_b.sent();
|
|
255
|
+
preserve = [{ columnPropertyName: 'body', paths: ['content'], whenType: 'string' }];
|
|
256
|
+
stalePayload = { id: doc.id, body: { content: 'v1', style: { color: 'red' } } };
|
|
257
|
+
_a = expect;
|
|
258
|
+
return [4 /*yield*/, rpc('updatePreserving', [docTable, stalePayload, preserve])];
|
|
259
|
+
case 3:
|
|
260
|
+
_a.apply(void 0, [_b.sent()]).toBe(1);
|
|
261
|
+
return [4 /*yield*/, db.get(docTable, { id: doc.id })];
|
|
262
|
+
case 4:
|
|
263
|
+
row = _b.sent();
|
|
264
|
+
expect(row.body).toEqual({ content: 'v2', style: { color: 'red' } });
|
|
265
|
+
return [2 /*return*/];
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}); });
|
|
269
|
+
test('concurrent RPCs on the shared service instance get isolated transactions', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
270
|
+
var doc, addedIds, inFlight, _i, addedIds_1, id, _a, _b;
|
|
271
|
+
var _c;
|
|
272
|
+
return __generator(this, function (_d) {
|
|
273
|
+
switch (_d.label) {
|
|
274
|
+
case 0: return [4 /*yield*/, db.insert(docTable, { title: 'd5', members: new db_1.ReferenceArray(docTable.name, ['seed']) })];
|
|
275
|
+
case 1:
|
|
276
|
+
doc = _d.sent();
|
|
277
|
+
addedIds = ['m1', 'm2', 'm3', 'm4', 'm5', 'm6'];
|
|
278
|
+
inFlight = [];
|
|
279
|
+
_i = 0, addedIds_1 = addedIds;
|
|
280
|
+
_d.label = 2;
|
|
281
|
+
case 2:
|
|
282
|
+
if (!(_i < addedIds_1.length)) return [3 /*break*/, 5];
|
|
283
|
+
id = addedIds_1[_i];
|
|
284
|
+
inFlight.push(rpc('updateArrayMembership', [
|
|
285
|
+
docTable,
|
|
286
|
+
{ recordId: doc.id, columnPropertyName: 'members', ops: [{ op: 'add', id: id, afterId: 'seed' }] },
|
|
287
|
+
]));
|
|
288
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 5); })];
|
|
289
|
+
case 3:
|
|
290
|
+
_d.sent();
|
|
291
|
+
_d.label = 4;
|
|
292
|
+
case 4:
|
|
293
|
+
_i++;
|
|
294
|
+
return [3 /*break*/, 2];
|
|
295
|
+
case 5: return [4 /*yield*/, Promise.all(inFlight)];
|
|
296
|
+
case 6:
|
|
297
|
+
_d.sent();
|
|
298
|
+
_a = expect;
|
|
299
|
+
_b = [[]];
|
|
300
|
+
return [4 /*yield*/, memberIds(doc.id)];
|
|
301
|
+
case 7:
|
|
302
|
+
_a.apply(void 0, [__spreadArray.apply(void 0, _b.concat([((_c = (_d.sent())) !== null && _c !== void 0 ? _c : []), true])).sort()]).toEqual(__spreadArray(__spreadArray([], addedIds, true), ['seed'], false).sort());
|
|
303
|
+
return [2 /*return*/];
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}); }, 60000);
|
|
307
|
+
test('updateArrayMembership rejects a non-ReferenceArrayColumn target', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
308
|
+
var doc;
|
|
309
|
+
return __generator(this, function (_a) {
|
|
310
|
+
switch (_a.label) {
|
|
311
|
+
case 0: return [4 /*yield*/, db.insert(docTable, { title: 'd6' })];
|
|
312
|
+
case 1:
|
|
313
|
+
doc = _a.sent();
|
|
314
|
+
return [4 /*yield*/, expect(rpc('updateArrayMembership', [
|
|
315
|
+
docTable,
|
|
316
|
+
{ recordId: doc.id, columnPropertyName: 'title', ops: [{ op: 'add', id: 'x', afterId: null }] },
|
|
317
|
+
])).rejects.toThrow('requires a ReferenceArrayColumn')];
|
|
318
|
+
case 2:
|
|
319
|
+
_a.sent();
|
|
320
|
+
return [2 /*return*/];
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}); });
|
|
324
|
+
});
|
|
325
|
+
//# sourceMappingURL=ServiceUpdateVerbs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceUpdateVerbs.test.js","sourceRoot":"","sources":["../../test/ServiceUpdateVerbs.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionPoolExhaustion.test.d.ts","sourceRoot":"","sources":["../../test/SessionPoolExhaustion.test.ts"],"names":[],"mappings":"AAMA,OAAO,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
+
extendStatics(d, b);
|
|
13
|
+
function __() { this.constructor = d; }
|
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
17
|
+
var __assign = (this && this.__assign) || function () {
|
|
18
|
+
__assign = Object.assign || function(t) {
|
|
19
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
20
|
+
s = arguments[i];
|
|
21
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
22
|
+
t[p] = s[p];
|
|
23
|
+
}
|
|
24
|
+
return t;
|
|
25
|
+
};
|
|
26
|
+
return __assign.apply(this, arguments);
|
|
27
|
+
};
|
|
28
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
29
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
30
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
31
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
32
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
33
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
34
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
38
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
39
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
40
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
41
|
+
function step(op) {
|
|
42
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
43
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
44
|
+
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;
|
|
45
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
46
|
+
switch (op[0]) {
|
|
47
|
+
case 0: case 1: t = op; break;
|
|
48
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
49
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
50
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
51
|
+
default:
|
|
52
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
53
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
54
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
55
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
56
|
+
if (t[2]) _.ops.pop();
|
|
57
|
+
_.trys.pop(); continue;
|
|
58
|
+
}
|
|
59
|
+
op = body.call(thisArg, _);
|
|
60
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
61
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
+
var db_1 = require("@proteinjs/db");
|
|
66
|
+
var db_transaction_context_1 = require("@proteinjs/db-transaction-context");
|
|
67
|
+
var db_driver_spanner_1 = require("@proteinjs/db-driver-spanner");
|
|
68
|
+
var getDropTestTable_1 = require("./util/getDropTestTable");
|
|
69
|
+
var SpannerEmulatorProvisioner_1 = require("./util/SpannerEmulatorProvisioner");
|
|
70
|
+
require("../generated/test/index");
|
|
71
|
+
var WedgeEmployeeTestTable = /** @class */ (function (_super) {
|
|
72
|
+
__extends(WedgeEmployeeTestTable, _super);
|
|
73
|
+
function WedgeEmployeeTestTable() {
|
|
74
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
75
|
+
_this.name = 'db_test_pool_wedge_employee';
|
|
76
|
+
_this.columns = (0, db_1.withRecordColumns)({
|
|
77
|
+
name: new db_1.StringColumn('name'),
|
|
78
|
+
department: new db_1.StringColumn('department'),
|
|
79
|
+
});
|
|
80
|
+
return _this;
|
|
81
|
+
}
|
|
82
|
+
return WedgeEmployeeTestTable;
|
|
83
|
+
}(db_1.Table));
|
|
84
|
+
var employeeTable = new WedgeEmployeeTestTable();
|
|
85
|
+
// Local table — not in any reflection source graph, so thread getTable explicitly.
|
|
86
|
+
var getTable = function () { return employeeTable; };
|
|
87
|
+
var spannerConfig = {
|
|
88
|
+
projectId: 'proteinjs-test',
|
|
89
|
+
instanceName: 'proteinjs-test',
|
|
90
|
+
databaseName: 'test',
|
|
91
|
+
};
|
|
92
|
+
// max: 1 makes pool mechanics observable in miniature. This file must stay its own jest
|
|
93
|
+
// file — SpannerDriver.SPANNER_DB is a process-wide static, so the max-1 pool would leak
|
|
94
|
+
// into other suites.
|
|
95
|
+
var spannerDriver = new db_driver_spanner_1.SpannerDriver(__assign(__assign({}, spannerConfig), { sessionPoolOptions: { max: 1, min: 1, acquireTimeout: 2000, fail: true } }), getTable);
|
|
96
|
+
var getSessionPool = function () {
|
|
97
|
+
var db = spannerDriver.getSpannerDb();
|
|
98
|
+
return db.pool_;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Pool mechanics at max=1 (plans/DB_PERF_PLAN.md P2):
|
|
102
|
+
* 1. The historical wedge — an operation inside a transaction acquiring a SECOND session while
|
|
103
|
+
* the transaction holds the only one — is DESIGNED OUT by the stateless transaction
|
|
104
|
+
* contract: every operation inside the body rides the held session, so the shape that
|
|
105
|
+
* bricked the process cannot be expressed. Proven here at max=1.
|
|
106
|
+
* 2. The exhaustion class that remains REAL — more concurrent transactions than sessions —
|
|
107
|
+
* is documented with two parallel transactions.
|
|
108
|
+
*/
|
|
109
|
+
describe('Session pool at max=1 (wedge designed out; real exhaustion documented)', function () {
|
|
110
|
+
var dropTable = (0, getDropTestTable_1.getDropTestTable)(spannerDriver);
|
|
111
|
+
var preconstructedDb = new db_1.Db(spannerDriver, getTable, new db_transaction_context_1.TransactionContext());
|
|
112
|
+
var txnDb = new db_1.Db(spannerDriver, getTable, new db_transaction_context_1.TransactionContext());
|
|
113
|
+
beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
114
|
+
var pool;
|
|
115
|
+
return __generator(this, function (_a) {
|
|
116
|
+
switch (_a.label) {
|
|
117
|
+
case 0: return [4 /*yield*/, SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.ensureProvisioned(spannerConfig)];
|
|
118
|
+
case 1:
|
|
119
|
+
_a.sent();
|
|
120
|
+
return [4 /*yield*/, spannerDriver.createDbIfNotExists()];
|
|
121
|
+
case 2:
|
|
122
|
+
_a.sent();
|
|
123
|
+
pool = getSessionPool();
|
|
124
|
+
pool.options.fail = false;
|
|
125
|
+
return [4 /*yield*/, spannerDriver.getTableManager().loadTable(employeeTable)];
|
|
126
|
+
case 3:
|
|
127
|
+
_a.sent();
|
|
128
|
+
pool.options.fail = true;
|
|
129
|
+
return [2 /*return*/];
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}); }, 60000);
|
|
133
|
+
afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
134
|
+
return __generator(this, function (_a) {
|
|
135
|
+
switch (_a.label) {
|
|
136
|
+
case 0:
|
|
137
|
+
getSessionPool().options.fail = false; // teardown queries queue like setup's
|
|
138
|
+
return [4 /*yield*/, dropTable(employeeTable)];
|
|
139
|
+
case 1:
|
|
140
|
+
_a.sent();
|
|
141
|
+
return [4 /*yield*/, SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.release()];
|
|
142
|
+
case 2:
|
|
143
|
+
_a.sent();
|
|
144
|
+
return [2 /*return*/];
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}); }, 60000);
|
|
148
|
+
test('SpannerConfig.sessionPoolOptions reach the session pool', function () {
|
|
149
|
+
var pool = getSessionPool();
|
|
150
|
+
expect(pool.options.max).toBe(1);
|
|
151
|
+
expect(pool.options.min).toBe(1);
|
|
152
|
+
expect(pool.options.acquireTimeout).toBe(2000);
|
|
153
|
+
expect(pool.options.fail).toBe(true);
|
|
154
|
+
});
|
|
155
|
+
test('wedge DESIGNED OUT: at max=1, a pre-constructed Db inside a transaction rides the held session and just works', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
156
|
+
var employee, inserted, committed;
|
|
157
|
+
return __generator(this, function (_a) {
|
|
158
|
+
switch (_a.label) {
|
|
159
|
+
case 0:
|
|
160
|
+
employee = {
|
|
161
|
+
name: 'PoolWedgeDesignedOut',
|
|
162
|
+
department: 'Engineering',
|
|
163
|
+
};
|
|
164
|
+
return [4 /*yield*/, txnDb.runTransaction(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
165
|
+
var emp, seen;
|
|
166
|
+
return __generator(this, function (_a) {
|
|
167
|
+
switch (_a.label) {
|
|
168
|
+
case 0: return [4 /*yield*/, txnDb.insert(employeeTable, employee)];
|
|
169
|
+
case 1:
|
|
170
|
+
emp = _a.sent();
|
|
171
|
+
return [4 /*yield*/, preconstructedDb.query(employeeTable, { name: employee.name })];
|
|
172
|
+
case 2:
|
|
173
|
+
seen = _a.sent();
|
|
174
|
+
expect(seen.length).toBe(1);
|
|
175
|
+
return [2 /*return*/, emp];
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}); })];
|
|
179
|
+
case 1:
|
|
180
|
+
inserted = _a.sent();
|
|
181
|
+
return [4 /*yield*/, preconstructedDb.query(employeeTable, { id: inserted.id })];
|
|
182
|
+
case 2:
|
|
183
|
+
committed = _a.sent();
|
|
184
|
+
expect(committed.length).toBe(1);
|
|
185
|
+
return [4 /*yield*/, txnDb.delete(employeeTable, { id: inserted.id })];
|
|
186
|
+
case 3:
|
|
187
|
+
_a.sent();
|
|
188
|
+
return [2 /*return*/];
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}); }, 30000);
|
|
192
|
+
test('real exhaustion class: a second PARALLEL transaction errors fast when the pool is spent (fail: true)', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
193
|
+
var releaseHold, holdGate, holder;
|
|
194
|
+
return __generator(this, function (_a) {
|
|
195
|
+
switch (_a.label) {
|
|
196
|
+
case 0:
|
|
197
|
+
holdGate = new Promise(function (resolve) { return (releaseHold = resolve); });
|
|
198
|
+
holder = txnDb.runTransaction(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
199
|
+
return __generator(this, function (_a) {
|
|
200
|
+
switch (_a.label) {
|
|
201
|
+
case 0: return [4 /*yield*/, holdGate];
|
|
202
|
+
case 1:
|
|
203
|
+
_a.sent();
|
|
204
|
+
return [2 /*return*/, 'held'];
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}); });
|
|
208
|
+
// Second transaction cannot get a session; with fail: true it errors immediately instead
|
|
209
|
+
// of joining the pool's silent infinite FIFO (the production-default hang this file's
|
|
210
|
+
// options exist to surface).
|
|
211
|
+
return [4 /*yield*/, expect(preconstructedDb.runTransaction(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
212
|
+
return [2 /*return*/, 'never-runs'];
|
|
213
|
+
}); }); })).rejects.toMatchObject({
|
|
214
|
+
name: 'SessionPoolExhaustedError',
|
|
215
|
+
})];
|
|
216
|
+
case 1:
|
|
217
|
+
// Second transaction cannot get a session; with fail: true it errors immediately instead
|
|
218
|
+
// of joining the pool's silent infinite FIFO (the production-default hang this file's
|
|
219
|
+
// options exist to surface).
|
|
220
|
+
_a.sent();
|
|
221
|
+
releaseHold();
|
|
222
|
+
return [4 /*yield*/, expect(holder).resolves.toBe('held')];
|
|
223
|
+
case 2:
|
|
224
|
+
_a.sent();
|
|
225
|
+
return [2 /*return*/];
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}); }, 30000);
|
|
229
|
+
});
|
|
230
|
+
//# sourceMappingURL=SessionPoolExhaustion.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionPoolExhaustion.test.js","sourceRoot":"","sources":["../../test/SessionPoolExhaustion.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionRecordTableQuery.test.d.ts","sourceRoot":"","sources":["../../test/SessionRecordTableQuery.test.ts"],"names":[],"mappings":"AAMA,OAAO,yBAAyB,CAAC"}
|