spice-couchbase 2.0.62 → 2.0.64

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.
@@ -0,0 +1,644 @@
1
+ "use strict";
2
+
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
6
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
7
+ function _toPrimitive(t, e) { if ("object" != typeof t || !t) return t; var r; if ("undefined" != typeof Symbol && void 0 !== (r = t[Symbol.toPrimitive])) { var i = r.call(t, e || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === e ? String : Number)(t); }
8
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
9
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
10
+ var assert = require("node:assert/strict");
11
+ var _require = require("node:test"),
12
+ test = _require.test;
13
+ var couchbase = require("couchbase");
14
+ var _require2 = require("./connectionHealth"),
15
+ createHealthMonitor = _require2.createHealthMonitor,
16
+ buildConnectOptions = _require2.buildConnectOptions,
17
+ isConnectivityError = _require2.isConnectivityError;
18
+ var config = {
19
+ nodes: "couchbase://db",
20
+ bucket: "saturn",
21
+ scope: "app",
22
+ username: "u",
23
+ password: "p"
24
+ };
25
+ var timeoutError = () => new couchbase.UnambiguousTimeoutError();
26
+
27
+ // A fake cluster whose probe behaviour can be flipped between healthy and
28
+ // wedged. `hang` makes operations never settle, like a stuck SDK.
29
+ function fakeCluster(id) {
30
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
31
+ _ref$healthy = _ref.healthy,
32
+ healthy = _ref$healthy === void 0 ? true : _ref$healthy,
33
+ _ref$hang = _ref.hang,
34
+ hang = _ref$hang === void 0 ? false : _ref$hang;
35
+ var cluster = {
36
+ id,
37
+ healthy,
38
+ hang,
39
+ closed: 0,
40
+ queries: 0,
41
+ kvStates: [couchbase.PingState.Ok],
42
+ close() {
43
+ return _asyncToGenerator(function* () {
44
+ cluster.closed += 1;
45
+ })();
46
+ },
47
+ query() {
48
+ cluster.queries += 1;
49
+ if (cluster.hang) return new Promise(() => {});
50
+ return cluster.healthy ? Promise.resolve({
51
+ rows: [{
52
+ $1: 1
53
+ }]
54
+ }) : Promise.reject(timeoutError());
55
+ },
56
+ bucket(name) {
57
+ var bucket = {
58
+ name,
59
+ cluster,
60
+ waitUntilReady() {
61
+ return _asyncToGenerator(function* () {
62
+ if (!cluster.healthy) throw timeoutError();
63
+ })();
64
+ },
65
+ ping() {
66
+ if (cluster.hang) return new Promise(() => {});
67
+ if (!cluster.healthy) return Promise.reject(timeoutError());
68
+ return Promise.resolve({
69
+ services: {
70
+ kv: cluster.kvStates.map(state => ({
71
+ state
72
+ }))
73
+ }
74
+ });
75
+ },
76
+ scope(scopeName) {
77
+ return {
78
+ name: scopeName,
79
+ bucket,
80
+ collection(collectionName) {
81
+ return {
82
+ name: collectionName,
83
+ cluster,
84
+ // Like `_default` inside a named scope: the collection does
85
+ // not exist, so KV operations on it always time out.
86
+ exists() {
87
+ return Promise.reject(timeoutError());
88
+ }
89
+ };
90
+ }
91
+ };
92
+ }
93
+ };
94
+ return bucket;
95
+ }
96
+ };
97
+ return cluster;
98
+ }
99
+ function handlesFor(cluster) {
100
+ var bucket = cluster.bucket(config.bucket);
101
+ var scope = bucket.scope(config.scope);
102
+ return {
103
+ cluster,
104
+ bucket,
105
+ scope,
106
+ collection: scope.collection("_default")
107
+ };
108
+ }
109
+ function setup() {
110
+ var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
111
+ _ref2$settings = _ref2.settings,
112
+ settings = _ref2$settings === void 0 ? {} : _ref2$settings,
113
+ connect = _ref2.connect,
114
+ clock = _ref2.clock;
115
+ var initial = fakeCluster("initial");
116
+ var handles = handlesFor(initial);
117
+ var globals = {
118
+ database: {
119
+ clusters: {
120
+ default: handles.cluster
121
+ },
122
+ buckets: {
123
+ default: handles.bucket
124
+ },
125
+ scopes: {
126
+ default: handles.scope
127
+ },
128
+ connections: {
129
+ default: handles.collection
130
+ }
131
+ },
132
+ checked_collections: {
133
+ users: true
134
+ },
135
+ db: {
136
+ collections: new Set(["users"])
137
+ }
138
+ };
139
+ var opened = [];
140
+ var time = clock || {
141
+ now: 1000
142
+ };
143
+ var terminated = [];
144
+ var logs = [];
145
+ var log = {
146
+ log: m => logs.push(m),
147
+ warn: m => logs.push(m),
148
+ error: m => logs.push(m)
149
+ };
150
+ var monitor = createHealthMonitor({
151
+ settings: _objectSpread({
152
+ healthIntervalMs: 0,
153
+ probeTimeoutMs: 20,
154
+ probeFailureThreshold: 2,
155
+ failureThreshold: 3,
156
+ failureWindowMs: 1000,
157
+ reconnectTimeoutMs: 50,
158
+ reconnectBackoffMinMs: 100,
159
+ reconnectBackoffMaxMs: 1000,
160
+ retireGraceMs: 5,
161
+ exitAfterMs: 10000
162
+ }, settings),
163
+ connect: connect || /*#__PURE__*/_asyncToGenerator(function* () {
164
+ var cluster = fakeCluster("fresh-".concat(opened.length + 1));
165
+ opened.push(cluster);
166
+ return cluster;
167
+ }),
168
+ now: () => time.now,
169
+ random: () => 0.5,
170
+ log,
171
+ getGlobals: () => globals,
172
+ terminate: () => terminated.push(time.now)
173
+ });
174
+ monitor.register("default", config);
175
+ return {
176
+ monitor,
177
+ initial,
178
+ globals,
179
+ opened,
180
+ time,
181
+ terminated,
182
+ logs
183
+ };
184
+ }
185
+ var sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
186
+ test("only connectivity errors count", () => {
187
+ assert.equal(isConnectivityError(timeoutError()), true);
188
+ assert.equal(isConnectivityError(new couchbase.AmbiguousTimeoutError()), true);
189
+ assert.equal(isConnectivityError(new couchbase.RequestCanceledError()), true);
190
+ assert.equal(isConnectivityError(new couchbase.ServiceNotAvailableError()), true);
191
+ assert.equal(isConnectivityError(new couchbase.DocumentNotFoundError()), false);
192
+ assert.equal(isConnectivityError(new Error("syntax error")), false);
193
+ assert.equal(isConnectivityError(undefined), false);
194
+ });
195
+ test("connect options carry only the timeouts that are set", () => {
196
+ assert.deepEqual(buildConnectOptions(config), {
197
+ username: "u",
198
+ password: "p"
199
+ });
200
+ assert.deepEqual(buildConnectOptions(_objectSpread(_objectSpread({}, config), {}, {
201
+ configProfile: "wanDevelopment",
202
+ timeouts: {
203
+ queryTimeout: "30000",
204
+ kvTimeout: undefined,
205
+ connectTimeout: ""
206
+ }
207
+ })), {
208
+ username: "u",
209
+ password: "p",
210
+ configProfile: "wanDevelopment",
211
+ timeouts: {
212
+ queryTimeout: 30000
213
+ }
214
+ });
215
+ });
216
+ test("a healthy probe leaves the connection alone", /*#__PURE__*/_asyncToGenerator(function* () {
217
+ var _setup = setup(),
218
+ monitor = _setup.monitor,
219
+ opened = _setup.opened,
220
+ globals = _setup.globals,
221
+ initial = _setup.initial;
222
+ assert.equal(yield monitor.check("default"), true);
223
+ assert.equal(opened.length, 0);
224
+ assert.equal(globals.database.clusters.default, initial);
225
+ assert.equal(monitor.status().default.healthy, true);
226
+ }));
227
+ test("the probe does not depend on the boot-time collection existing", /*#__PURE__*/_asyncToGenerator(function* () {
228
+ // The fake collection's KV operations always time out; ping still succeeds.
229
+ var _setup2 = setup({
230
+ settings: {
231
+ probeFailureThreshold: 1
232
+ }
233
+ }),
234
+ monitor = _setup2.monitor,
235
+ opened = _setup2.opened;
236
+ assert.equal(yield monitor.check("default"), true);
237
+ assert.equal(opened.length, 0);
238
+ assert.equal(monitor.status().default.healthy, true);
239
+ }));
240
+ test("one answering KV node is enough, none is unhealthy", /*#__PURE__*/_asyncToGenerator(function* () {
241
+ var _setup3 = setup({
242
+ settings: {
243
+ probeFailureThreshold: 1
244
+ }
245
+ }),
246
+ monitor = _setup3.monitor,
247
+ initial = _setup3.initial,
248
+ opened = _setup3.opened;
249
+ var _couchbase$PingState = couchbase.PingState,
250
+ Ok = _couchbase$PingState.Ok,
251
+ Timeout = _couchbase$PingState.Timeout,
252
+ Failed = _couchbase$PingState.Error;
253
+ initial.kvStates = [Timeout, Ok, Failed];
254
+ assert.equal(yield monitor.check("default"), true);
255
+ assert.equal(opened.length, 0);
256
+ initial.kvStates = [Timeout, Failed];
257
+ yield monitor.check("default");
258
+ assert.equal(opened.length, 1);
259
+ }));
260
+ test("probe failures say which check failed", /*#__PURE__*/_asyncToGenerator(function* () {
261
+ var _setup4 = setup({
262
+ settings: {
263
+ probeFailureThreshold: 1
264
+ },
265
+ connect: function () {
266
+ var _connect = _asyncToGenerator(function* () {
267
+ return fakeCluster("bad", {
268
+ healthy: false
269
+ });
270
+ });
271
+ function connect() {
272
+ return _connect.apply(this, arguments);
273
+ }
274
+ return connect;
275
+ }()
276
+ }),
277
+ monitor = _setup4.monitor,
278
+ initial = _setup4.initial;
279
+ initial.kvStates = [];
280
+ yield monitor.check("default");
281
+ assert.match(monitor.status().default.lastError, /waitUntilReady failed/);
282
+ var query = setup({
283
+ settings: {
284
+ probeFailureThreshold: 1
285
+ }
286
+ });
287
+ query.initial.query = () => Promise.reject(timeoutError());
288
+ yield query.monitor.check("default");
289
+ assert.match(query.logs.join("\n"), /unhealthy: Query probe failed/);
290
+ var kv = setup({
291
+ settings: {
292
+ probeFailureThreshold: 1
293
+ }
294
+ });
295
+ kv.initial.kvStates = [];
296
+ yield kv.monitor.check("default");
297
+ assert.match(kv.logs.join("\n"), /unhealthy: KV ping failed: no endpoint responded/);
298
+ }));
299
+ test("non-connectivity errors never trigger a probe", /*#__PURE__*/_asyncToGenerator(function* () {
300
+ var _setup5 = setup(),
301
+ monitor = _setup5.monitor,
302
+ initial = _setup5.initial;
303
+ for (var i = 0; i < 10; i++) {
304
+ monitor.recordOutcome("default", new couchbase.DocumentNotFoundError());
305
+ }
306
+ yield sleep(5);
307
+ assert.equal(initial.queries, 0);
308
+ }));
309
+ test("one failed probe is not enough, two trigger a reconnect", /*#__PURE__*/_asyncToGenerator(function* () {
310
+ var _setup6 = setup(),
311
+ monitor = _setup6.monitor,
312
+ initial = _setup6.initial,
313
+ opened = _setup6.opened;
314
+ initial.healthy = false;
315
+ yield monitor.check("default");
316
+ assert.equal(opened.length, 0);
317
+ assert.equal(monitor.status().default.healthy, true);
318
+ yield monitor.check("default");
319
+ assert.equal(opened.length, 1);
320
+ assert.equal(monitor.status().default.healthy, true);
321
+ assert.equal(monitor.status().default.generation, 2);
322
+ }));
323
+ test("a burst of operation timeouts probes and reconnects at once", /*#__PURE__*/_asyncToGenerator(function* () {
324
+ var _setup7 = setup(),
325
+ monitor = _setup7.monitor,
326
+ initial = _setup7.initial,
327
+ opened = _setup7.opened,
328
+ globals = _setup7.globals;
329
+ initial.healthy = false;
330
+ for (var i = 0; i < 3; i++) monitor.recordOutcome("default", timeoutError());
331
+ yield sleep(10);
332
+ assert.equal(opened.length, 1);
333
+ assert.equal(globals.database.clusters.default, opened[0]);
334
+ }));
335
+ test("timeouts outside the window do not add up", /*#__PURE__*/_asyncToGenerator(function* () {
336
+ var _setup8 = setup(),
337
+ monitor = _setup8.monitor,
338
+ initial = _setup8.initial,
339
+ opened = _setup8.opened,
340
+ time = _setup8.time;
341
+ initial.healthy = false;
342
+ monitor.recordOutcome("default", timeoutError());
343
+ monitor.recordOutcome("default", timeoutError());
344
+ time.now += 2000;
345
+ monitor.recordOutcome("default", timeoutError());
346
+ yield sleep(10);
347
+ assert.equal(initial.queries, 0);
348
+ assert.equal(opened.length, 0);
349
+ }));
350
+ test("reconnect swaps every global handle and resets collection caches", /*#__PURE__*/_asyncToGenerator(function* () {
351
+ var _setup9 = setup(),
352
+ monitor = _setup9.monitor,
353
+ initial = _setup9.initial,
354
+ opened = _setup9.opened,
355
+ globals = _setup9.globals;
356
+ initial.healthy = false;
357
+ yield monitor.check("default");
358
+ yield monitor.check("default");
359
+ var fresh = opened[0];
360
+ assert.equal(globals.database.clusters.default, fresh);
361
+ assert.equal(globals.database.buckets.default.cluster, fresh);
362
+ assert.equal(globals.database.scopes.default.bucket.cluster, fresh);
363
+ assert.equal(globals.database.connections.default.cluster, fresh);
364
+ assert.deepEqual(globals.checked_collections, {});
365
+ assert.equal(globals.db.collections.size, 0);
366
+ }));
367
+ test("the replaced cluster is closed after the grace period", /*#__PURE__*/_asyncToGenerator(function* () {
368
+ var _setup0 = setup(),
369
+ monitor = _setup0.monitor,
370
+ initial = _setup0.initial;
371
+ initial.healthy = false;
372
+ yield monitor.check("default");
373
+ yield monitor.check("default");
374
+ assert.equal(initial.closed, 0);
375
+ yield sleep(20);
376
+ assert.equal(initial.closed, 1);
377
+ }));
378
+ test("concurrent triggers share a single reconnect", /*#__PURE__*/_asyncToGenerator(function* () {
379
+ var release;
380
+ var opened = [];
381
+ var _setup1 = setup({
382
+ settings: {
383
+ probeFailureThreshold: 1,
384
+ reconnectTimeoutMs: 1000
385
+ },
386
+ connect: () => new Promise(resolve => {
387
+ release = () => {
388
+ var cluster = fakeCluster("fresh");
389
+ opened.push(cluster);
390
+ resolve(cluster);
391
+ };
392
+ })
393
+ }),
394
+ monitor = _setup1.monitor,
395
+ initial = _setup1.initial;
396
+ initial.healthy = false;
397
+ var first = monitor.check("default");
398
+ yield sleep(5);
399
+ var others = [monitor.check("default"), monitor.reconnect("default")];
400
+ for (var i = 0; i < 5; i++) monitor.recordOutcome("default", timeoutError());
401
+ release();
402
+ yield Promise.all([first, ...others]);
403
+ assert.equal(opened.length, 1);
404
+ assert.equal(monitor.status().default.generation, 2);
405
+ }));
406
+ test("a probe that hangs is cut off by the hard deadline", /*#__PURE__*/_asyncToGenerator(function* () {
407
+ var _setup10 = setup({
408
+ settings: {
409
+ probeFailureThreshold: 1
410
+ }
411
+ }),
412
+ monitor = _setup10.monitor,
413
+ initial = _setup10.initial,
414
+ opened = _setup10.opened;
415
+ initial.hang = true;
416
+ // The deadline timer is unref'd; keep the loop alive while the probe hangs.
417
+ var keepAlive = setInterval(() => {}, 1000);
418
+ try {
419
+ var started = Date.now();
420
+ yield monitor.check("default");
421
+ assert.ok(Date.now() - started < 1500);
422
+ assert.equal(opened.length, 1);
423
+ } finally {
424
+ clearInterval(keepAlive);
425
+ }
426
+ }));
427
+ test("a failed reconnect backs off and keeps the old cluster", /*#__PURE__*/_asyncToGenerator(function* () {
428
+ var opened = [];
429
+ var _setup11 = setup({
430
+ settings: {
431
+ probeFailureThreshold: 1
432
+ },
433
+ connect: function () {
434
+ var _connect2 = _asyncToGenerator(function* () {
435
+ var cluster = fakeCluster("bad-".concat(opened.length + 1), {
436
+ healthy: false
437
+ });
438
+ opened.push(cluster);
439
+ return cluster;
440
+ });
441
+ function connect() {
442
+ return _connect2.apply(this, arguments);
443
+ }
444
+ return connect;
445
+ }()
446
+ }),
447
+ monitor = _setup11.monitor,
448
+ initial = _setup11.initial,
449
+ globals = _setup11.globals,
450
+ time = _setup11.time;
451
+ initial.healthy = false;
452
+ yield monitor.check("default");
453
+ assert.equal(opened.length, 1);
454
+ assert.equal(opened[0].closed, 1, "unverified cluster is closed");
455
+ assert.equal(globals.database.clusters.default, initial);
456
+ assert.equal(monitor.status().default.reconnectAttempts, 1);
457
+
458
+ // Inside the backoff window: probe only, no new connect.
459
+ yield monitor.check("default");
460
+ assert.equal(opened.length, 1);
461
+ time.now += 150;
462
+ yield monitor.check("default");
463
+ assert.equal(opened.length, 2);
464
+ assert.equal(monitor.status().default.reconnectAttempts, 2);
465
+ }));
466
+ test("a connection that recovers on its own is marked healthy again", /*#__PURE__*/_asyncToGenerator(function* () {
467
+ var _setup12 = setup({
468
+ settings: {
469
+ probeFailureThreshold: 1
470
+ },
471
+ connect: function () {
472
+ var _connect3 = _asyncToGenerator(function* () {
473
+ return fakeCluster("bad", {
474
+ healthy: false
475
+ });
476
+ });
477
+ function connect() {
478
+ return _connect3.apply(this, arguments);
479
+ }
480
+ return connect;
481
+ }()
482
+ }),
483
+ monitor = _setup12.monitor,
484
+ initial = _setup12.initial,
485
+ time = _setup12.time;
486
+ initial.healthy = false;
487
+ yield monitor.check("default");
488
+ assert.equal(monitor.status().default.healthy, false);
489
+ initial.healthy = true;
490
+ time.now += 5000;
491
+ yield monitor.check("default");
492
+ var status = monitor.status().default;
493
+ assert.equal(status.healthy, true);
494
+ assert.equal(status.reconnectAttempts, 0);
495
+ assert.equal(status.unhealthySince, null);
496
+ }));
497
+ test("staying unhealthy past the limit terminates the process once", /*#__PURE__*/_asyncToGenerator(function* () {
498
+ var _setup13 = setup({
499
+ settings: {
500
+ probeFailureThreshold: 1,
501
+ exitAfterMs: 1000
502
+ },
503
+ connect: function () {
504
+ var _connect4 = _asyncToGenerator(function* () {
505
+ return fakeCluster("bad", {
506
+ healthy: false
507
+ });
508
+ });
509
+ function connect() {
510
+ return _connect4.apply(this, arguments);
511
+ }
512
+ return connect;
513
+ }()
514
+ }),
515
+ monitor = _setup13.monitor,
516
+ initial = _setup13.initial,
517
+ time = _setup13.time,
518
+ terminated = _setup13.terminated;
519
+ initial.healthy = false;
520
+ yield monitor.check("default");
521
+ assert.equal(terminated.length, 0);
522
+ time.now += 1500;
523
+ yield monitor.check("default");
524
+ time.now += 1500;
525
+ yield monitor.check("default");
526
+ assert.equal(terminated.length, 1);
527
+ }));
528
+ test("exitAfterMs of 0 never terminates", /*#__PURE__*/_asyncToGenerator(function* () {
529
+ var _setup14 = setup({
530
+ settings: {
531
+ probeFailureThreshold: 1,
532
+ exitAfterMs: 0
533
+ },
534
+ connect: function () {
535
+ var _connect5 = _asyncToGenerator(function* () {
536
+ return fakeCluster("bad", {
537
+ healthy: false
538
+ });
539
+ });
540
+ function connect() {
541
+ return _connect5.apply(this, arguments);
542
+ }
543
+ return connect;
544
+ }()
545
+ }),
546
+ monitor = _setup14.monitor,
547
+ initial = _setup14.initial,
548
+ time = _setup14.time,
549
+ terminated = _setup14.terminated;
550
+ initial.healthy = false;
551
+ for (var i = 0; i < 5; i++) {
552
+ time.now += 100000;
553
+ yield monitor.check("default");
554
+ }
555
+ assert.equal(terminated.length, 0);
556
+ }));
557
+ test("stop() halts reconnects and closes retired clusters", /*#__PURE__*/_asyncToGenerator(function* () {
558
+ var _setup15 = setup({
559
+ settings: {
560
+ probeFailureThreshold: 1,
561
+ retireGraceMs: 60000
562
+ }
563
+ }),
564
+ monitor = _setup15.monitor,
565
+ initial = _setup15.initial,
566
+ opened = _setup15.opened;
567
+ initial.healthy = false;
568
+ yield monitor.check("default");
569
+ assert.equal(opened.length, 1);
570
+ yield monitor.stop();
571
+ assert.equal(initial.closed, 1);
572
+ opened[0].healthy = false;
573
+ yield monitor.check("default");
574
+ yield monitor.reconnect("default");
575
+ assert.equal(opened.length, 1);
576
+ }));
577
+ test("the interval probe runs when enabled", /*#__PURE__*/_asyncToGenerator(function* () {
578
+ var _setup16 = setup({
579
+ settings: {
580
+ healthIntervalMs: 5,
581
+ probeFailureThreshold: 1
582
+ }
583
+ }),
584
+ monitor = _setup16.monitor,
585
+ initial = _setup16.initial,
586
+ opened = _setup16.opened;
587
+ initial.healthy = false;
588
+ yield sleep(40);
589
+ assert.ok(opened.length >= 1);
590
+ yield monitor.stop();
591
+ }));
592
+ test("a Database instance follows the swapped globals", /*#__PURE__*/_asyncToGenerator(function* () {
593
+ var path = require.resolve("./index");
594
+ delete require.cache[path];
595
+ var previousSpice = global.spice;
596
+ var _setup17 = setup({
597
+ settings: {
598
+ probeFailureThreshold: 1
599
+ }
600
+ }),
601
+ monitor = _setup17.monitor,
602
+ initial = _setup17.initial,
603
+ opened = _setup17.opened,
604
+ globals = _setup17.globals;
605
+ global.spice = _objectSpread(_objectSpread({}, globals), {}, {
606
+ config: {
607
+ database: {
608
+ connections: {
609
+ default: _objectSpread({}, config)
610
+ }
611
+ }
612
+ }
613
+ });
614
+ // Point the shared module-level monitor at this test's monitor.
615
+ var key = Symbol.for("spice-couchbase.health-monitor");
616
+ var previousMonitor = globalThis[key];
617
+ globalThis[key] = monitor;
618
+ try {
619
+ // Keep a reference to the same globals object the monitor mutates.
620
+ global.spice.database = globals.database;
621
+ // The constructor reads the bucket name off the boot-time collection.
622
+ globals.database.connections.default._scope = {
623
+ _bucket: {
624
+ _name: "saturn"
625
+ }
626
+ };
627
+ var Database = require("./index");
628
+ var db = new Database("default");
629
+ assert.equal(db.cluster, initial);
630
+ var oldCollection = db.collection;
631
+ assert.equal(oldCollection.cluster, initial);
632
+ initial.healthy = false;
633
+ yield monitor.check("default");
634
+ assert.equal(opened.length, 1);
635
+ assert.equal(db.cluster, opened[0]);
636
+ assert.equal(db.collection.cluster, opened[0]);
637
+ assert.notEqual(db.collection, oldCollection);
638
+ assert.deepEqual(Database.healthStatus().default.generation, 2);
639
+ } finally {
640
+ globalThis[key] = previousMonitor;
641
+ global.spice = previousSpice;
642
+ delete require.cache[path];
643
+ }
644
+ }));