@mark1russell7/service 0.5.11 → 0.5.13

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/build/redis.js CHANGED
@@ -1,10 +1,8 @@
1
1
  import { realClock } from "./clock.js";
2
2
  import { heartbeat } from "./heartbeat.js";
3
3
  import { i as heartbeatDetection } from "./timing-DGRi3XCI.js";
4
- import { t as mayReissue } from "./operation-DL5RxFds.js";
5
4
  import { backoffDelay } from "./backoff.js";
6
- import { quantity, valueIn } from "@mark1russell7/quantity";
7
- import { connect } from "node:net";
5
+ import { C as notSent, D as readyWait, F as timeProblems, G as immediate, J as keepaliveSilent, K as keepaliveAnswered, M as sendWithReissue, N as socketEnds, O as retryBackoff, P as stepChecks, R as withinBound, S as ms, U as WHAT, V as MANIFESTATIONS, W as firstDetector, X as unwatched, Y as kernelGiveUp, _ as inFlight, a as helloDial, b as message, d as clientProblems, f as clientRecorder, h as finiteMs, j as roundTripCheck, k as retryProblems, l as attachClient, m as dialCheck, n as closeTimer, q as keepaliveReset, r as transition, t as clientKnob, u as clientBounds, w as operationTable, x as missesProblems, y as localStateCheck } from "./machine-BhTRu3u9.js";
8
6
  //#region src/redis/connection.ts
9
7
  /**
10
8
  * This factory makes an ioredis client. It loads ioredis only when a client connects, thus a
@@ -15,13 +13,6 @@ const ioredis = async (options) => {
15
13
  };
16
14
  //#endregion
17
15
  //#region src/redis/meets.ts
18
- const never = {
19
- value: "infinite",
20
- unit: "s"
21
- };
22
- const s = (value) => quantity(Math.round(value * 1e6) / 1e6, "s");
23
- const seconds = (amount) => amount.value === "infinite" ? Number.POSITIVE_INFINITY : valueIn(amount, "s");
24
- const plus = (amount, more) => amount.value === "infinite" ? never : s(seconds(amount) + more);
25
16
  /**
26
17
  * This function gives the manifestations that a Redis client can meet, and the detectors of each, from
27
18
  * its knobs. A reset or a FIN arrives on the next segment. A black hole and a host that is gone give
@@ -29,7 +20,6 @@ const plus = (amount, more) => amount.value === "infinite" ? never : s(seconds(a
29
20
  * segment. Thus TCP keepalive does not fire on them, and only the client's own timers find them.
30
21
  */
31
22
  const meetings = (name, knobs, heartbeat) => {
32
- const keepalive = plus(knobs.keepalive_idle, 10);
33
23
  const watchdog = (situation) => ({
34
24
  by: "heartbeat_detection_time",
35
25
  within: heartbeat,
@@ -48,27 +38,17 @@ const meetings = (name, knobs, heartbeat) => {
48
38
  situation: "in flight",
49
39
  effect: "the command fails as indeterminate, and the state of the connection does not change"
50
40
  };
51
- const giveUp = {
52
- by: "retrans_giveup_time",
53
- within: knobs.retrans_giveup_time,
54
- situation: "in flight",
55
- effect: "the kernel gives up the retransmissions and closes the socket"
56
- };
57
- const silent = (manifestation, what) => ({
41
+ const giveUp = kernelGiveUp(knobs.retrans_giveup_time);
42
+ const silent = (manifestation) => ({
58
43
  manifestation,
59
- what,
44
+ what: WHAT[manifestation],
60
45
  detectors: [
61
46
  command,
62
47
  writeoff,
63
48
  watchdog("in flight"),
64
49
  giveUp,
65
50
  watchdog("idle"),
66
- {
67
- by: "keepalive_idle",
68
- within: keepalive,
69
- situation: "idle",
70
- effect: "TCP keepalive gives up, and the socket closes"
71
- }
51
+ keepaliveSilent(knobs.keepalive_idle)
72
52
  ]
73
53
  });
74
54
  const acknowledged = (manifestation, what) => ({
@@ -79,55 +59,30 @@ const meetings = (name, knobs, heartbeat) => {
79
59
  writeoff,
80
60
  watchdog("in flight"),
81
61
  watchdog("idle"),
82
- {
83
- by: "keepalive_idle",
84
- within: never,
85
- situation: "idle",
86
- effect: "the kernel of the server answers each probe"
87
- }
62
+ keepaliveAnswered()
88
63
  ]
89
64
  });
90
- const immediate = (situation, effect) => ({
91
- by: "the next segment",
92
- within: s(0),
93
- situation,
94
- effect
95
- });
96
65
  return [
97
66
  {
98
67
  manifestation: "rst",
99
- what: "the server answers each segment with a reset, and refuses each new connection",
68
+ what: WHAT.rst,
100
69
  detectors: [
101
70
  immediate("in flight", "the command fails, and the client connects again, and each attempt is refused"),
102
71
  watchdog("idle"),
103
- {
104
- by: "keepalive_idle",
105
- within: keepalive.value === "infinite" ? never : knobs.keepalive_idle,
106
- situation: "idle",
107
- effect: "the first probe gets a reset"
108
- }
72
+ keepaliveReset(knobs.keepalive_idle)
109
73
  ]
110
74
  },
111
75
  {
112
76
  manifestation: "fin",
113
- what: "the process of the server ends, and its kernel closes the connection",
77
+ what: WHAT.fin,
114
78
  detectors: [immediate("in flight", "the close arrives, and the command fails"), immediate("idle", "the close arrives")]
115
79
  },
116
- silent("blackhole", "the network drops each segment in the two directions"),
117
- silent("freeze-host", "the host of the server stops, without a close: the death without a close"),
118
- acknowledged("freeze-process", "the process of the server stops, and its kernel stays up"),
80
+ silent("blackhole"),
81
+ silent("freeze-host"),
82
+ acknowledged("freeze-process", WHAT["freeze-process"]),
119
83
  acknowledged("app-stall", "the server stops its replies for a time, for example a long command, and its kernel stays up")
120
84
  ];
121
85
  };
122
- /** This function gives the first detector of a manifestation in a situation, or null when no detector has an end (C3). */
123
- const firstDetector = (meeting, situation) => {
124
- return meeting.detectors.filter((detector) => detector.situation === situation && detector.within.value !== "infinite").sort((a, b) => seconds(a.within) - seconds(b.within))[0] ?? null;
125
- };
126
- /** This function gives each manifestation and situation that no detector of the client finds: the standing rule, as a query (C3, E9). */
127
- const unwatched = (meets) => meets.flatMap((meeting) => ["in flight", "idle"].flatMap((situation) => firstDetector(meeting, situation) === null ? [{
128
- manifestation: meeting.manifestation,
129
- situation
130
- }] : []));
131
86
  //#endregion
132
87
  //#region src/redis/operations.ts
133
88
  /**
@@ -242,63 +197,23 @@ const commandName = (command, args) => {
242
197
  };
243
198
  //#endregion
244
199
  //#region src/redis/client.ts
245
- const ms = (amount) => amount.value === "infinite" ? Number.POSITIVE_INFINITY : valueIn(amount, "ms");
246
- const finite = (amount) => {
247
- const value = ms(amount);
248
- return Number.isFinite(value) ? value : void 0;
249
- };
250
- const message = (error) => error instanceof Error ? error.message : String(error);
251
- /**
252
- * This function gives the backoff of the tries to connect: from `retry_base`, doubling to
253
- * `retry_cap`, each with a jitter up to the base. The client rounds each delay to a whole millisecond.
254
- */
255
- const retryBackoff = (knobs) => ({
256
- base: ms(knobs.retry_base),
257
- factor: 2,
258
- cap: ms(knobs.retry_cap),
259
- jitter: {
260
- kind: "add",
261
- amount: ms(knobs.retry_base)
262
- }
263
- });
264
200
  /** This function gives the problems of a spec: the knobs that the client cannot use. */
265
201
  const specProblems = (name, spec) => {
266
202
  const problems = [];
267
203
  const { knobs } = spec;
268
- if (!Number.isInteger(spec.heartbeatMisses) || spec.heartbeatMisses < 1) problems.push(`${name}'s watchdog closes the connection after ${spec.heartbeatMisses} misses, not a whole number above zero`);
204
+ problems.push(...missesProblems(name, spec.heartbeatMisses, "watchdog"));
269
205
  if (knobs.max_connection_age.value !== "infinite") problems.push(`${name} cannot replace its connection at an age: max_connection_age must be "infinite"`);
270
- for (const [knob, amount] of Object.entries(knobs)) if (amount.value !== "infinite" && !(ms(amount) >= 0)) problems.push(`${name}'s ${knob} is not a time of zero or more`);
206
+ problems.push(...timeProblems(name, knobs));
271
207
  if (ms(knobs.request_timeout) <= 0) problems.push(`${name}'s request_timeout is not above zero: each command must have a bound`);
272
208
  if (ms(knobs.heartbeat_timeout) <= 0) problems.push(`${name}'s heartbeat_timeout is not above zero`);
273
- if (ms(knobs.retry_cap) < ms(knobs.retry_base)) problems.push(`${name}'s retry_cap is below its retry_base`);
209
+ problems.push(...retryProblems(name, knobs));
274
210
  return problems;
275
211
  };
276
212
  /** This dial function opens a TCP connection, sends an inline PING, and waits for +PONG. */
277
- const tcpDial = (host, port, signal) => new Promise((resolve, reject) => {
278
- if (signal.aborted) {
279
- reject(/* @__PURE__ */ new Error("the dial was aborted"));
280
- return;
281
- }
282
- const socket = connect({
283
- host,
284
- port
285
- });
286
- let reply = "";
287
- const end = (error) => {
288
- signal.removeEventListener("abort", onAbort);
289
- socket.destroy();
290
- if (error === void 0) resolve();
291
- else reject(error);
292
- };
293
- const onAbort = () => end(/* @__PURE__ */ new Error("the dial was aborted"));
294
- signal.addEventListener("abort", onAbort, { once: true });
295
- socket.once("connect", () => socket.write("PING\r\n"));
296
- socket.on("data", (chunk) => {
297
- reply += chunk.toString();
298
- if (reply.includes("\r\n")) end(reply.startsWith("+PONG") ? void 0 : /* @__PURE__ */ new Error(`the reply was ${reply.trim()}`));
299
- });
300
- socket.once("error", (error) => end(error));
301
- socket.once("close", () => end(/* @__PURE__ */ new Error("the server closed the dial")));
213
+ const tcpDial = helloDial("PING\r\n", (received) => {
214
+ const reply = received.toString();
215
+ if (!reply.includes("\r\n")) return "more";
216
+ return reply.startsWith("+PONG") ? null : /* @__PURE__ */ new Error(`the reply was ${reply.trim()}`);
302
217
  });
303
218
  /**
304
219
  * This function makes a Redis client. It is a dependency of a service, with ioredis under it:
@@ -309,6 +224,9 @@ const tcpDial = (host, port, signal) => new Promise((resolve, reject) => {
309
224
  * - It records the server's id of each connection at `ready` (D1).
310
225
  * - A watchdog sends a PING in the band of the connection, and it connects again after the misses
311
226
  * of the declaration. It also starts a client that stopped (principle 19).
227
+ *
228
+ * The outcomes, the second try, the commands in flight, the bounded close and the checks come
229
+ * from the core of the clients. This entry gives what ioredis does in its own way.
312
230
  */
313
231
  const redisClient = (name, spec, options = {}) => {
314
232
  const problems = specProblems(name, spec);
@@ -319,10 +237,7 @@ const redisClient = (name, spec, options = {}) => {
319
237
  const create = options.create ?? ioredis;
320
238
  const dial = options.dial ?? tcpDial;
321
239
  const turn = options.turn ?? (() => new Promise((resolve) => setImmediate(resolve)));
322
- const operations = {
323
- ...REDIS_OPERATIONS,
324
- ...spec.operations
325
- };
240
+ const operations = operationTable(REDIS_OPERATIONS, spec.operations);
326
241
  const requestTimeout = ms(knobs.request_timeout);
327
242
  const detection = heartbeatDetection(knobs.heartbeat_interval, knobs.heartbeat_timeout, spec.heartbeatMisses);
328
243
  const backoff = retryBackoff(knobs);
@@ -330,18 +245,10 @@ const redisClient = (name, spec, options = {}) => {
330
245
  let status = "none";
331
246
  let closing = false;
332
247
  const joins = [];
333
- const inFlight = /* @__PURE__ */ new Set();
334
- const readyWaiters = /* @__PURE__ */ new Set();
248
+ const flight = inFlight();
249
+ const readied = readyWait(clock, () => connection?.status === "ready");
335
250
  const listeners = [];
336
- const record = (from, to, on, detail) => options.record?.({
337
- at: clock.now(),
338
- machine: "client",
339
- instance: name,
340
- from,
341
- to,
342
- on,
343
- ...detail === void 0 ? {} : { detail }
344
- });
251
+ const record = clientRecorder(options.record, clock, name);
345
252
  let retrySince = null;
346
253
  const retryStrategy = (times) => {
347
254
  const now = clock.now();
@@ -361,8 +268,8 @@ const redisClient = (name, spec, options = {}) => {
361
268
  lazyConnect: true,
362
269
  connectTimeout: ms(knobs.connect_bound),
363
270
  commandTimeout: requestTimeout,
364
- socketTimeout: finite(knobs.driver_writeoff_time),
365
- keepAlive: finite(knobs.keepalive_idle) ?? false,
271
+ socketTimeout: finiteMs(knobs.driver_writeoff_time),
272
+ keepAlive: finiteMs(knobs.keepalive_idle) ?? false,
366
273
  enableOfflineQueue: false,
367
274
  autoResendUnfulfilledCommands: false,
368
275
  maxRetriesPerRequest: null,
@@ -378,11 +285,7 @@ const redisClient = (name, spec, options = {}) => {
378
285
  error: text,
379
286
  reply: true
380
287
  };
381
- if (/isn't writeable|enableOfflineQueue/i.test(text)) return {
382
- outcome: "error",
383
- error: text,
384
- reply: false
385
- };
288
+ if (/isn't writeable|enableOfflineQueue/i.test(text)) return notSent(text);
386
289
  return {
387
290
  outcome: "indeterminate",
388
291
  error: text
@@ -408,22 +311,16 @@ const redisClient = (name, spec, options = {}) => {
408
311
  generation,
409
312
  at,
410
313
  clientId,
411
- localAddress: socket?.localAddress ?? null,
412
- localPort: socket?.localPort ?? null,
413
- remoteAddress: socket?.remoteAddress ?? null,
414
- remotePort: socket?.remotePort ?? null
314
+ ...socketEnds(socket)
415
315
  });
416
316
  record("ready", "ready", "join", `generation ${generation}, client id ${clientId ?? "unknown"}`);
417
- for (const wake of [...readyWaiters]) wake();
317
+ readied.wake();
418
318
  };
419
319
  const onStatus = (to) => () => {
420
320
  const from = status;
421
321
  status = to;
422
322
  record(from, to, `status.${to}`);
423
- if (to === "close" || to === "end") for (const settle of [...inFlight]) settle({
424
- outcome: "indeterminate",
425
- error: `the connection closed with the command in flight (${from})`
426
- });
323
+ if (to === "close" || to === "end") flight.settleAll(`the connection closed with the command in flight (${from})`);
427
324
  if (to === "ready") onReady();
428
325
  };
429
326
  const watch = (c) => {
@@ -443,96 +340,27 @@ const redisClient = (name, spec, options = {}) => {
443
340
  c.on("error", onError);
444
341
  listeners.push(["error", onError]);
445
342
  };
446
- /** This function waits until the connection is ready, for `within` milliseconds at most. It gives true when it is ready. */
447
- const waitReady = (within, signal) => new Promise((resolve) => {
448
- if (connection?.status === "ready") {
449
- resolve(true);
450
- return;
451
- }
452
- let cancel = () => {};
453
- const done = (value) => {
454
- readyWaiters.delete(wake);
455
- cancel();
456
- signal?.removeEventListener("abort", aborted);
457
- resolve(value);
458
- };
459
- const wake = () => done(true);
460
- const aborted = () => done(false);
461
- readyWaiters.add(wake);
462
- cancel = clock.after(within, () => done(connection?.status === "ready"));
463
- signal?.addEventListener("abort", aborted, { once: true });
464
- });
465
343
  const attempt = (command, args, signal) => {
466
344
  const c = connection;
467
- if (c === null) return Promise.resolve({
468
- outcome: "error",
469
- error: `${name} has not connected`,
470
- reply: false
471
- });
472
- if (c.status !== "ready") return Promise.resolve({
473
- outcome: "error",
474
- error: `${name} is ${c.status}, not ready: the command did not leave the client`,
475
- reply: false
476
- });
477
- if (signal?.aborted) return Promise.resolve({
478
- outcome: "error",
479
- error: "the caller aborted the command before it left the client",
480
- reply: false
481
- });
482
- return new Promise((resolve) => {
483
- let settled = false;
484
- const settle = (value) => {
485
- if (settled) return;
486
- settled = true;
487
- inFlight.delete(settle);
488
- signal?.removeEventListener("abort", aborted);
489
- resolve(value);
490
- };
491
- const aborted = () => settle({
492
- outcome: "indeterminate",
493
- error: "the caller abandoned the command after it was sent"
494
- });
495
- inFlight.add(settle);
496
- signal?.addEventListener("abort", aborted, { once: true });
345
+ if (c === null) return Promise.resolve(notSent(`${name} has not connected`));
346
+ if (c.status !== "ready") return Promise.resolve(notSent(`${name} is ${c.status}, not ready: the command did not leave the client`));
347
+ if (signal?.aborted) return Promise.resolve(notSent("the caller aborted the command before it left the client"));
348
+ return flight.track(signal, "the caller abandoned the command after it was sent", (settle) => {
497
349
  c.call(command, ...args).then((value) => settle({
498
350
  outcome: "ok",
499
351
  value
500
352
  }), (error) => settle(failed(error)));
501
353
  });
502
354
  };
503
- const send = async (command, args = [], sendOptions = {}) => {
504
- const { signal } = sendOptions;
505
- const operation = sendOptions.reissue === false ? void 0 : operations[commandName(command, args)];
506
- const started = clock.now();
507
- const first = await attempt(command, args, signal);
508
- if (first.outcome === "ok") return {
509
- outcome: "ok",
510
- value: first.value,
511
- attempts: 1
512
- };
513
- const again = !(first.outcome === "error" && first.reply) && operation !== void 0 && signal?.aborted !== true && mayReissue(operation, quantity((clock.now() - started) / 1e3, "s"));
514
- const left = requestTimeout - (clock.now() - started);
515
- if (!again || left <= 0 || !await waitReady(left, signal)) return {
516
- ...first,
517
- attempts: 1
518
- };
519
- record(status, status, "command.reissue", commandName(command, args));
520
- const bound = new AbortController();
521
- const end = clock.after(Math.max(0, requestTimeout - (clock.now() - started)), () => bound.abort());
522
- const forward = () => bound.abort();
523
- signal?.addEventListener("abort", forward, { once: true });
524
- const second = await attempt(command, args, bound.signal);
525
- end();
526
- signal?.removeEventListener("abort", forward);
527
- return second.outcome === "ok" ? {
528
- outcome: "ok",
529
- value: second.value,
530
- attempts: 2
531
- } : {
532
- ...second,
533
- attempts: 2
534
- };
535
- };
355
+ const send = (command, args = [], sendOptions = {}) => sendWithReissue({
356
+ clock,
357
+ bound: requestTimeout,
358
+ operation: operations[commandName(command, args)],
359
+ options: sendOptions,
360
+ attempt: (signal) => attempt(command, args, signal),
361
+ beforeAgain: (left, signal) => readied.wait(left, signal),
362
+ onReissue: () => record(status, status, "command.reissue", commandName(command, args))
363
+ });
536
364
  let watchdog = null;
537
365
  const startWatchdog = () => heartbeat({
538
366
  interval: ms(knobs.heartbeat_interval),
@@ -577,15 +405,8 @@ const redisClient = (name, spec, options = {}) => {
577
405
  watchdog = null;
578
406
  const c = connection;
579
407
  if (c === null) return;
580
- const quit = c.quit().then(() => "quit", () => "quit");
581
- let cancel = () => {};
582
- const bound = new Promise((resolve) => {
583
- cancel = clock.after(ms(knobs.close_bound), () => resolve("bound"));
584
- });
585
408
  const startedClose = clock.now();
586
- const first = await Promise.race([quit, bound]);
587
- cancel();
588
- if (first === "bound") record(status, status, "close.bound");
409
+ if (!await withinBound(clock, ms(knobs.close_bound), c.quit())) record(status, status, "close.bound");
589
410
  if (c.status !== "end") c.disconnect(false);
590
411
  const ended = (within) => c.status === "end" ? Promise.resolve() : new Promise((resolve) => {
591
412
  let stop = () => {};
@@ -605,10 +426,7 @@ const redisClient = (name, spec, options = {}) => {
605
426
  }
606
427
  for (const [event, listener] of listeners) c.off(event, listener);
607
428
  listeners.length = 0;
608
- for (const settle of [...inFlight]) settle({
609
- outcome: "indeterminate",
610
- error: "the client closed with the command in flight"
611
- });
429
+ flight.settleAll("the client closed with the command in flight");
612
430
  status = "end";
613
431
  }
614
432
  };
@@ -631,32 +449,11 @@ const redisClient = (name, spec, options = {}) => {
631
449
  },
632
450
  operations
633
451
  };
634
- const checks = (checkOptions) => {
635
- const made = [];
636
- const declare = (step, ownConnection, run) => {
637
- if (!(step in checkOptions.steps)) return;
638
- made.push([{
639
- name: `${name}.${step}`,
640
- dependency: name,
641
- step,
642
- ownConnection,
643
- gates: checkOptions.steps[step] ?? null,
644
- poll: checkOptions.poll
645
- }, run]);
646
- };
647
- declare("local-state", true, () => connection?.status === "ready" ? "ok" : "error");
648
- declare("round-trip", true, async (signal) => {
649
- return (await send("PING", [], {
650
- signal,
651
- reissue: false
652
- })).outcome === "ok" ? "ok" : "error";
653
- });
654
- declare("dial", false, async (signal) => {
655
- await dial(spec.host, spec.port, signal);
656
- return "ok";
657
- });
658
- return made;
659
- };
452
+ const checks = (checkOptions) => stepChecks(name, checkOptions, {
453
+ "local-state": localStateCheck(() => connection?.status === "ready"),
454
+ "round-trip": roundTripCheck((sendOptions) => send("PING", [], sendOptions)),
455
+ dial: dialCheck(dial, spec.host, spec.port)
456
+ });
660
457
  return {
661
458
  name,
662
459
  declaration,
@@ -668,23 +465,8 @@ const redisClient = (name, spec, options = {}) => {
668
465
  joins,
669
466
  send,
670
467
  checks,
671
- attach(svc, checkOptions) {
672
- svc.dependency(name, declaration, handle);
673
- for (const [check, run] of checks(checkOptions)) svc.check(check, run);
674
- return svc;
675
- },
676
- problems(description) {
677
- const found = [];
678
- const teardown = description.shutdown.phases.find((phase) => phase.name === "tear down dependencies");
679
- if (teardown === void 0) found.push(`${name} needs the phase "tear down dependencies" to close`);
680
- else if (ms(knobs.close_bound) >= valueIn(teardown.cap, "ms")) found.push(`${name}'s close_bound of ${ms(knobs.close_bound)} ms does not fit in the cap of "tear down dependencies"`);
681
- for (const check of description.checks) {
682
- if (check.dependency !== name) continue;
683
- const slowest = valueIn(check.poll.timeout, "ms");
684
- if (check.step === "round-trip" && requestTimeout > slowest + valueIn(check.poll.interval, "ms") * (1 + check.poll.jitter)) found.push(`${name}'s request_timeout outlives one jittered poll of ${check.name} (B7, O13)`);
685
- }
686
- return found;
687
- }
468
+ attach: (svc, checkOptions) => attachClient(svc, name, declaration, handle, checks(checkOptions)),
469
+ problems: (description) => clientProblems(name, description, clientBounds(knobs))
688
470
  };
689
471
  };
690
472
  //#endregion
@@ -842,19 +624,6 @@ const replyOf = (limiter, reply) => {
842
624
  };
843
625
  //#endregion
844
626
  //#region src/redis/machine.ts
845
- const t = (id, from, on, to, extra = {}) => ({
846
- id,
847
- from,
848
- on,
849
- to,
850
- ...extra
851
- });
852
- const knob = (key) => ({
853
- key,
854
- scope: "client",
855
- unit: "s",
856
- default: null
857
- });
858
627
  /** The states where the connection exists or tries to exist, thus where it can close. */
859
628
  const LIVE = [
860
629
  "connecting",
@@ -932,10 +701,10 @@ const REDIS_CLIENT_MACHINE = {
932
701
  }
933
702
  },
934
703
  knobs: {
935
- connect_bound: knob("connectTimeout"),
936
- driver_writeoff_time: knob("socketTimeout"),
937
- heartbeat_interval: knob("watchdog.interval"),
938
- close_bound: knob("close.bound")
704
+ connect_bound: clientKnob("connectTimeout"),
705
+ driver_writeoff_time: clientKnob("socketTimeout"),
706
+ heartbeat_interval: clientKnob("watchdog.interval"),
707
+ close_bound: clientKnob("close.bound")
939
708
  },
940
709
  timers: {
941
710
  connect_timeout: {
@@ -968,41 +737,33 @@ const REDIS_CLIENT_MACHINE = {
968
737
  fires: "heartbeat",
969
738
  note: "a PING on the connection of the application"
970
739
  },
971
- close: {
972
- duration: {
973
- knob: "close_bound",
974
- unit: "s"
975
- },
976
- arms: ["close.request"],
977
- cancels: ["status.end"],
978
- fires: "close.bound"
979
- }
740
+ close: closeTimer()
980
741
  },
981
742
  transitions: [
982
- t("connect", [
743
+ transition("connect", [
983
744
  "none",
984
745
  "reconnecting",
985
746
  "end",
986
747
  "close"
987
748
  ], "status.connecting", "connecting"),
988
- t("tcp", "connecting", "status.connect", "connect"),
989
- t("ready", "connect", "status.ready", "ready"),
990
- t("close", [...LIVE], "status.close", "close"),
991
- t("retry", "close", "status.reconnecting", "reconnecting"),
992
- t("end", [...LIVE, "close"], "status.end", "end"),
993
- t("join", "ready", "join", "ready"),
994
- t("miss", "ready", "watchdog.miss", "ready"),
995
- t("watchdog-reconnect", "ready", "watchdog.reconnect", "ready"),
996
- t("revive", "end", "watchdog.revive", "end"),
997
- t("window-ended", "close", "retry.window-ended", "close"),
998
- ...ANY.map((state) => t(`error-${state}`, state, "error", state)),
999
- ...ANY.map((state) => t(`connect-failed-${state}`, state, "connect.failed", state)),
1000
- ...ANY.map((state) => t(`reissue-${state}`, state, "command.reissue", state)),
1001
- ...ANY.map((state) => t(`close-bound-${state}`, state, "close.bound", state, { timer: "close" })),
1002
- ...ANY.map((state) => t(`close-destroy-${state}`, state, "close.destroy", state))
749
+ transition("tcp", "connecting", "status.connect", "connect"),
750
+ transition("ready", "connect", "status.ready", "ready"),
751
+ transition("close", [...LIVE], "status.close", "close"),
752
+ transition("retry", "close", "status.reconnecting", "reconnecting"),
753
+ transition("end", [...LIVE, "close"], "status.end", "end"),
754
+ transition("join", "ready", "join", "ready"),
755
+ transition("miss", "ready", "watchdog.miss", "ready"),
756
+ transition("watchdog-reconnect", "ready", "watchdog.reconnect", "ready"),
757
+ transition("revive", "end", "watchdog.revive", "end"),
758
+ transition("window-ended", "close", "retry.window-ended", "close"),
759
+ ...ANY.map((state) => transition(`error-${state}`, state, "error", state)),
760
+ ...ANY.map((state) => transition(`connect-failed-${state}`, state, "connect.failed", state)),
761
+ ...ANY.map((state) => transition(`reissue-${state}`, state, "command.reissue", state)),
762
+ ...ANY.map((state) => transition(`close-bound-${state}`, state, "close.bound", state, { timer: "close" })),
763
+ ...ANY.map((state) => transition(`close-destroy-${state}`, state, "close.destroy", state))
1003
764
  ]
1004
765
  };
1005
766
  //#endregion
1006
- export { LIMITER_SCRIPT, REDIS_CLIENT_MACHINE, REDIS_OPERATIONS, commandName, firstDetector, heartbeatDetection, ioredis, meetings, redisClient, redisLimiterStore, retryBackoff, specProblems, tcpDial, unwatched };
767
+ export { LIMITER_SCRIPT, MANIFESTATIONS, REDIS_CLIENT_MACHINE, REDIS_OPERATIONS, commandName, firstDetector, heartbeatDetection, ioredis, meetings, redisClient, redisLimiterStore, retryBackoff, specProblems, tcpDial, unwatched };
1007
768
 
1008
769
  //# sourceMappingURL=redis.js.map