@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.
- 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/SpannerDriver.d.ts +12 -0
- package/dist/src/SpannerDriver.d.ts.map +1 -1
- package/dist/src/SpannerDriver.js +62 -13
- package/dist/src/SpannerDriver.js.map +1 -1
- package/dist/src/SpannerLivenessMonitor.d.ts.map +1 -1
- package/dist/src/SpannerLivenessMonitor.js +11 -2
- 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/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 +23 -0
- package/dist/test/SpannerLivenessMonitor.test.js.map +1 -1
- 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 +1 -1
- package/generated/test/index.ts +3 -1
- package/package.json +5 -5
- package/src/SpannerDriver.ts +35 -6
- package/src/SpannerLivenessMonitor.ts +12 -2
- package/test/ServiceUpdateVerbs.test.ts +188 -0
- package/test/SessionRecordTableQuery.test.ts +118 -0
- package/test/SpannerLivenessMonitor.test.ts +15 -0
- package/test/index.ts +1 -0
- 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
|
|
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(
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,4CAA2C;AAE3C,4FAA4F;AAC5F,IAAM,uBAAuB,GAAG,CAAC,CAAC,CAAC,uBAAuB,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC;AAElF;IAQE,gCAAoB,EAAY;QAAZ,OAAE,GAAF,EAAE,CAAU;QAHxB,WAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QACrD,kBAAa,GAAG,KAAK,CAAC;IAEK,CAAC;IAEpC,8FAA8F;IAC9F,sCAAK,GAAL;QAAA,iBASC;QARC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,UAAC,KAAU;;YAC7B,KAAI,CAAC,MAAM,CAAC,IAAI,CAAC;gBACf,OAAO,EAAE,4EAA4E;gBACrF,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,EAAE,YAAY,EAAE,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,MAAM,CAAC,KAAK,CAAC,EAAE;aAC1E,CAAC,CAAC;YACH,KAAK,KAAI,CAAC,cAAc,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mFAAmF;IACnF,4CAAW,GAAX,UAAY,KAAU;QACpB,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,CAAC,EAAE;YAClD,OAAO;SACR;QACD,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;IAC7B,CAAC;IAED,uBAAuB;IAET,+CAAc,GAA5B;;;;;;;wBACE,IAAI,IAAI,CAAC,aAAa,EAAE;4BACtB,sBAAO,CAAC,mGAAmG;yBAC5G;wBACD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;;;;wBAEf,OAAO,GAAG,CAAC;;;6BAAE,CAAA,OAAO,GAAG,sBAAsB,CAAC,eAAe,CAAC,MAAM,CAAA;wBAC3E,qBAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAA;;wBAAjE,SAAiE,CAAC;;;;wBAEhE,qBAAM,IAAI,CAAC,KAAK,EAAE,EAAA;;wBAAlB,SAAkB,CAAC;wBACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;wBACzF,sBAAO;;;wBAEP,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;4BACf,OAAO,EAAE,8BAA8B;4BACvC,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,YAAY,EAAE,MAAA,OAAK,aAAL,OAAK,uBAAL,OAAK,CAAE,OAAO,mCAAI,MAAM,CAAC,OAAK,CAAC,EAAE;yBAC7E,CAAC,CAAC;;;wBAVwE,OAAO,EAAE,CAAA;;;wBAaxF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;4BAChB,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"SpannerLivenessMonitor.js","sourceRoot":"","sources":["../../src/SpannerLivenessMonitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 @@
|
|
|
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) {
|