@proteinjs/db-driver-spanner 1.12.3 → 1.13.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.
Files changed (40) hide show
  1. package/dist/generated/index.js +1 -1
  2. package/dist/generated/index.js.map +1 -1
  3. package/dist/generated/test/index.d.ts.map +1 -1
  4. package/dist/generated/test/index.js +3 -1
  5. package/dist/generated/test/index.js.map +1 -1
  6. package/dist/src/SpannerDriver.d.ts +12 -0
  7. package/dist/src/SpannerDriver.d.ts.map +1 -1
  8. package/dist/src/SpannerDriver.js +62 -13
  9. package/dist/src/SpannerDriver.js.map +1 -1
  10. package/dist/src/SpannerLivenessMonitor.d.ts.map +1 -1
  11. package/dist/src/SpannerLivenessMonitor.js +11 -2
  12. package/dist/src/SpannerLivenessMonitor.js.map +1 -1
  13. package/dist/test/ServiceUpdateVerbs.test.d.ts +2 -0
  14. package/dist/test/ServiceUpdateVerbs.test.d.ts.map +1 -0
  15. package/dist/test/ServiceUpdateVerbs.test.js +325 -0
  16. package/dist/test/ServiceUpdateVerbs.test.js.map +1 -0
  17. package/dist/test/SessionRecordTableQuery.test.d.ts +2 -0
  18. package/dist/test/SessionRecordTableQuery.test.d.ts.map +1 -0
  19. package/dist/test/SessionRecordTableQuery.test.js +185 -0
  20. package/dist/test/SessionRecordTableQuery.test.js.map +1 -0
  21. package/dist/test/SpannerLivenessMonitor.test.js +23 -0
  22. package/dist/test/SpannerLivenessMonitor.test.js.map +1 -1
  23. package/dist/test/index.d.ts +1 -0
  24. package/dist/test/index.d.ts.map +1 -1
  25. package/dist/test/index.js +1 -0
  26. package/dist/test/index.js.map +1 -1
  27. package/dist/test/util/serviceUpdateVerbsTestTables.d.ts +45 -0
  28. package/dist/test/util/serviceUpdateVerbsTestTables.d.ts.map +1 -0
  29. package/dist/test/util/serviceUpdateVerbsTestTables.js +100 -0
  30. package/dist/test/util/serviceUpdateVerbsTestTables.js.map +1 -0
  31. package/generated/index.ts +1 -1
  32. package/generated/test/index.ts +3 -1
  33. package/package.json +5 -5
  34. package/src/SpannerDriver.ts +35 -6
  35. package/src/SpannerLivenessMonitor.ts +12 -2
  36. package/test/ServiceUpdateVerbs.test.ts +188 -0
  37. package/test/SessionRecordTableQuery.test.ts +118 -0
  38. package/test/SpannerLivenessMonitor.test.ts +15 -0
  39. package/test/index.ts +1 -0
  40. package/test/util/serviceUpdateVerbsTestTables.ts +55 -0
@@ -40,6 +40,15 @@ exports.SpannerLivenessMonitor = void 0;
40
40
  var logger_1 = require("@proteinjs/logger");
41
41
  /** grpc status codes that indicate connectivity trouble rather than an application error */
42
42
  var CONNECTIVITY_GRPC_CODES = [4 /* DEADLINE_EXCEEDED */, 14 /* UNAVAILABLE */];
43
+ /**
44
+ * Restart-requested exit code — the supervision contract shared with @proteinjs/build's
45
+ * serve-package (ServePackageSupervisor.RESTART_REQUEST_EXIT_CODE): a supervised process
46
+ * exiting with this code is respawned with bounded backoff instead of being treated as a plain
47
+ * failure (which the supervisor mirrors, i.e. stays down). Orchestrators that restart on any
48
+ * nonzero exit (systemd, Kubernetes) treat it like any other failure code, so it is safe
49
+ * everywhere. Hard-coded by design: the contract crosses a process boundary, like a signal.
50
+ */
51
+ var RESTART_REQUEST_EXIT_CODE = 86;
43
52
  var SpannerLivenessMonitor = /** @class */ (function () {
44
53
  function SpannerLivenessMonitor(db) {
45
54
  this.db = db;
@@ -108,7 +117,7 @@ var SpannerLivenessMonitor = /** @class */ (function () {
108
117
  return [3 /*break*/, 2];
109
118
  case 8:
110
119
  this.logger.error({
111
- message: "Db unreachable after sustained probing; exiting so supervision can restart into a valid state",
120
+ message: "Db unreachable after sustained probing; exiting restart-requested (code ".concat(RESTART_REQUEST_EXIT_CODE, ") so supervision respawns into a valid state"),
112
121
  });
113
122
  this.exit();
114
123
  return [3 /*break*/, 10];
@@ -139,7 +148,7 @@ var SpannerLivenessMonitor = /** @class */ (function () {
139
148
  return new Promise(function (resolve) { return setTimeout(resolve, ms); });
140
149
  };
141
150
  SpannerLivenessMonitor.prototype.exit = function () {
142
- process.exit(1);
151
+ process.exit(RESTART_REQUEST_EXIT_CODE);
143
152
  };
144
153
  SpannerLivenessMonitor.PROBE_SQL = 'SELECT 1';
145
154
  SpannerLivenessMonitor.PROBE_TIMEOUT_MS = 10000;
@@ -1 +1 @@
1
- {"version":3,"file":"SpannerLivenessMonitor.js","sourceRoot":"","sources":["../../src/SpannerLivenessMonitor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SpannerLivenessMonitor.js","sourceRoot":"","sources":["../../src/SpannerLivenessMonitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import '../generated/test/index';
2
+ //# sourceMappingURL=ServiceUpdateVerbs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ServiceUpdateVerbs.test.d.ts","sourceRoot":"","sources":["../../test/ServiceUpdateVerbs.test.ts"],"names":[],"mappings":"AAmBA,OAAO,yBAAyB,CAAC"}
@@ -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,2 @@
1
+ import '../generated/test/index';
2
+ //# sourceMappingURL=SessionRecordTableQuery.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionRecordTableQuery.test.d.ts","sourceRoot":"","sources":["../../test/SessionRecordTableQuery.test.ts"],"names":[],"mappings":"AAMA,OAAO,yBAAyB,CAAC"}
@@ -0,0 +1,185 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
+ return new (P || (P = Promise))(function (resolve, reject) {
20
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
24
+ });
25
+ };
26
+ var __generator = (this && this.__generator) || function (thisArg, body) {
27
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
28
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29
+ function verb(n) { return function (v) { return step([n, v]); }; }
30
+ function step(op) {
31
+ if (f) throw new TypeError("Generator is already executing.");
32
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
33
+ 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;
34
+ if (y = 0, t) op = [op[0] & 2, t.value];
35
+ switch (op[0]) {
36
+ case 0: case 1: t = op; break;
37
+ case 4: _.label++; return { value: op[1], done: false };
38
+ case 5: _.label++; y = op[1]; op = [0]; continue;
39
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
40
+ default:
41
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45
+ if (t[2]) _.ops.pop();
46
+ _.trys.pop(); continue;
47
+ }
48
+ op = body.call(thisArg, _);
49
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
+ }
52
+ };
53
+ var __importDefault = (this && this.__importDefault) || function (mod) {
54
+ return (mod && mod.__esModule) ? mod : { "default": mod };
55
+ };
56
+ Object.defineProperty(exports, "__esModule", { value: true });
57
+ var moment_1 = __importDefault(require("moment"));
58
+ var db_driver_spanner_1 = require("@proteinjs/db-driver-spanner");
59
+ var db_1 = require("@proteinjs/db");
60
+ var db_transaction_context_1 = require("@proteinjs/db-transaction-context");
61
+ var getDropTestTable_1 = require("./util/getDropTestTable");
62
+ var SpannerEmulatorProvisioner_1 = require("./util/SpannerEmulatorProvisioner");
63
+ require("../generated/test/index");
64
+ /** Mirrors @proteinjs/user SessionTable column-for-column (namespaced test table name). */
65
+ var SessionShapeTable = /** @class */ (function (_super) {
66
+ __extends(SessionShapeTable, _super);
67
+ function SessionShapeTable() {
68
+ var _this = _super !== null && _super.apply(this, arguments) || this;
69
+ _this.name = 'db_test_session_record_table_query';
70
+ _this.columns = (0, db_1.withRecordColumns)({
71
+ sessionId: new db_1.StringColumn('session_id'),
72
+ session: new db_1.StringColumn('serialized_session', {}, 4000),
73
+ expires: new db_1.DateColumn('expires'),
74
+ userEmail: new db_1.StringColumn('user_email'),
75
+ });
76
+ return _this;
77
+ }
78
+ return SessionShapeTable;
79
+ }(db_1.Table));
80
+ var table = new SessionShapeTable();
81
+ var getTable = function (tableName) {
82
+ if (tableName === table.name) {
83
+ return table;
84
+ }
85
+ throw new Error("Unexpected table lookup in test: ".concat(tableName));
86
+ };
87
+ var spannerDriver = new db_driver_spanner_1.SpannerDriver({
88
+ projectId: 'proteinjs-test',
89
+ instanceName: 'proteinjs-test',
90
+ databaseName: 'test',
91
+ }, getTable);
92
+ /**
93
+ * What DbSessionStore serializes into a row (shape from a real dev session). `updated` is
94
+ * stamped explicitly for deterministic newest-first assertions: the insert-time default takes
95
+ * moment() per row, and rows landing in the same millisecond would make the order ambiguous.
96
+ */
97
+ var storeShapedRow = function (n, updatedMs) { return ({
98
+ sessionId: "test-session-".concat(n),
99
+ session: JSON.stringify({
100
+ cookie: { originalMaxAge: 5184000000, expires: '2026-10-01T00:00:00.000Z', httpOnly: true, path: '/' },
101
+ passport: { user: "user-".concat(n, "@test.local") },
102
+ }),
103
+ expires: new Date(Date.now() + 5184000000),
104
+ userEmail: "user-".concat(n, "@test.local"),
105
+ updated: (0, moment_1.default)(updatedMs),
106
+ }); };
107
+ describe('Session-shaped record table query (the admin Sessions table path)', function () {
108
+ var dropTable = (0, getDropTestTable_1.getDropTestTable)(spannerDriver);
109
+ // Writes as the session store writes (system db), reads as the record table reads.
110
+ var systemDb = new db_1.Db(spannerDriver, getTable, new db_transaction_context_1.TransactionContext(), true);
111
+ var db = new db_1.Db(spannerDriver, getTable, new db_transaction_context_1.TransactionContext());
112
+ beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
113
+ return __generator(this, function (_a) {
114
+ switch (_a.label) {
115
+ case 0: return [4 /*yield*/, SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.ensureProvisioned({
116
+ projectId: 'proteinjs-test',
117
+ instanceName: 'proteinjs-test',
118
+ databaseName: 'test',
119
+ })];
120
+ case 1:
121
+ _a.sent();
122
+ return [4 /*yield*/, dropTable(table)];
123
+ case 2:
124
+ _a.sent();
125
+ return [4 /*yield*/, spannerDriver.getTableManager().loadTable(table)];
126
+ case 3:
127
+ _a.sent();
128
+ return [2 /*return*/];
129
+ }
130
+ });
131
+ }); }, 60000);
132
+ afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
133
+ return __generator(this, function (_a) {
134
+ switch (_a.label) {
135
+ case 0: return [4 /*yield*/, dropTable(table)];
136
+ case 1:
137
+ _a.sent();
138
+ return [4 /*yield*/, SpannerEmulatorProvisioner_1.SpannerEmulatorProvisioner.release()];
139
+ case 2:
140
+ _a.sent();
141
+ return [2 /*return*/];
142
+ }
143
+ });
144
+ }); }, 30000);
145
+ test('store-written session rows all come back through the record-table query, newest-first', function () { return __awaiter(void 0, void 0, void 0, function () {
146
+ var base, n, qb, rows, countQb, _a;
147
+ return __generator(this, function (_b) {
148
+ switch (_b.label) {
149
+ case 0:
150
+ base = Date.now() - 60000;
151
+ n = 1;
152
+ _b.label = 1;
153
+ case 1:
154
+ if (!(n <= 3)) return [3 /*break*/, 4];
155
+ return [4 /*yield*/, systemDb.insert(table, storeShapedRow(n, base + n * 1000))];
156
+ case 2:
157
+ _b.sent();
158
+ _b.label = 3;
159
+ case 3:
160
+ n++;
161
+ return [3 /*break*/, 1];
162
+ case 4:
163
+ qb = new db_1.QueryBuilderFactory()
164
+ .createQueryBuilder(table)
165
+ .sort([{ field: 'updated', desc: true }])
166
+ .paginate({ start: 0, end: 10 });
167
+ return [4 /*yield*/, db.query(table, qb)];
168
+ case 5:
169
+ rows = _b.sent();
170
+ expect(rows.map(function (row) { return row.sessionId; })).toEqual(['test-session-3', 'test-session-2', 'test-session-1']);
171
+ // Round-trip fidelity of the store-shaped fields the table displays.
172
+ expect(rows[0].userEmail).toBe('user-3@test.local');
173
+ expect(JSON.parse(rows[0].session).passport.user).toBe('user-3@test.local');
174
+ expect(rows[0].expires).toBeTruthy();
175
+ countQb = new db_1.QueryBuilderFactory().createQueryBuilder(table);
176
+ _a = expect;
177
+ return [4 /*yield*/, db.getRowCount(table, countQb)];
178
+ case 6:
179
+ _a.apply(void 0, [_b.sent()]).toBe(3);
180
+ return [2 /*return*/];
181
+ }
182
+ });
183
+ }); }, 60000);
184
+ });
185
+ //# sourceMappingURL=SessionRecordTableQuery.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionRecordTableQuery.test.js","sourceRoot":"","sources":["../../test/SessionRecordTableQuery.test.ts"],"names":[],"mappings":"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"}
@@ -122,6 +122,29 @@ describe('SpannerLivenessMonitor', function () {
122
122
  }
123
123
  });
124
124
  }); });
125
+ test('the sustained-failure exit is RESTART-REQUESTED (code 86) so supervision respawns instead of staying down', function () { return __awaiter(void 0, void 0, void 0, function () {
126
+ var processExitSpy, check;
127
+ return __generator(this, function (_a) {
128
+ switch (_a.label) {
129
+ case 0:
130
+ // The serve-package contract (ServePackageSupervisor.RESTART_REQUEST_EXIT_CODE): 86 asks
131
+ // the supervisor for a respawn with backoff; a plain exit(1) is mirrored and stays down —
132
+ // observed as a dev server dead all night after a transient network outage.
133
+ exitSpy.mockRestore();
134
+ processExitSpy = jest.spyOn(process, 'exit').mockImplementation((function () { return undefined; }));
135
+ probeSpy.mockRejectedValue(new Error('14 UNAVAILABLE: fake'));
136
+ check = internals.verifyLiveness();
137
+ return [4 /*yield*/, jest.advanceTimersByTimeAsync(ALL_PROBE_DELAYS_MS)];
138
+ case 1:
139
+ _a.sent();
140
+ return [4 /*yield*/, check];
141
+ case 2:
142
+ _a.sent();
143
+ expect(processExitSpy).toHaveBeenCalledWith(86);
144
+ return [2 /*return*/];
145
+ }
146
+ });
147
+ }); });
125
148
  test('burst coalescing: reportError while a check is in flight triggers one probe cycle', function () { return __awaiter(void 0, void 0, void 0, function () {
126
149
  return __generator(this, function (_a) {
127
150
  switch (_a.label) {