@mark1russell7/kind 0.12.4 → 0.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/README.md +2 -0
- package/build/index.d.ts +2 -2
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/{judge-BbzdXnBz.d.ts → judge-B_wVAwjx.d.ts} +40 -14
- package/build/{judge-45z0yZ-r.js → judge-Bc84w-no.js} +85 -54
- package/build/judge-Bc84w-no.js.map +1 -0
- package/build/judge.d.ts +2 -2
- package/build/judge.js +1 -1
- package/package.json +5 -4
- package/build/judge-45z0yZ-r.js.map +0 -1
|
@@ -559,6 +559,20 @@ interface BacklogTerm<A = Quantity> {
|
|
|
559
559
|
* Without it, the drain adds only r, as in SYS-42.
|
|
560
560
|
*/
|
|
561
561
|
readonly drains?: boolean | undefined;
|
|
562
|
+
/**
|
|
563
|
+
* This time (SYS-45) is the largest drain time of one slow session. In a run, at most one session on
|
|
564
|
+
* the target drains longer than d.hi, up to this time. Thus the window closes up to
|
|
565
|
+
* (n − 1) × d.hi + this time after the band end (`backlogEnd`). With `drains`, each session
|
|
566
|
+
* can fail more requests in the drain (`drainBand`). Without it, each session drains in d.
|
|
567
|
+
*/
|
|
568
|
+
readonly slowest?: A | undefined;
|
|
569
|
+
/**
|
|
570
|
+
* With this flag (SYS-45), the band of the last failed request (`overshootBand`) opens at the
|
|
571
|
+
* low end of the end band, plus n × d.lo. The last failed request can start up to one
|
|
572
|
+
* turn before the window closes. The end band also opens one turn before the band end. The judge
|
|
573
|
+
* already checks the last failure from that low end. Without it, that band opens at n × d.lo.
|
|
574
|
+
*/
|
|
575
|
+
readonly early?: boolean | undefined;
|
|
562
576
|
}
|
|
563
577
|
/** A replica is one pod of the service at the start of a run. */
|
|
564
578
|
interface Replica {
|
|
@@ -648,8 +662,17 @@ declare const showBand: (band: Band) => string;
|
|
|
648
662
|
/**
|
|
649
663
|
* This function gives the end band of a window with the backlog term (`BacklogTerm`). It adds n × d
|
|
650
664
|
* to each end of `end`, the end band without the term. The value n is the sessions on the target.
|
|
665
|
+
* A term with `slowest` (SYS-45) adds (n − 1) × d.hi + `slowest` to the high end instead.
|
|
666
|
+
*/
|
|
667
|
+
declare const backlogEnd: (end: Band, term: Pick<BacklogTerm, "drain"> & Partial<Pick<BacklogTerm, "slowest">>, sessions: number) => Band;
|
|
668
|
+
/**
|
|
669
|
+
* This function gives the band of the start of the last failed request of a window with the backlog
|
|
670
|
+
* term, from the band end (the high end of `end`). This is the overshoot of a run. Its high end is
|
|
671
|
+
* the high end of `backlogEnd`. Without `early`, its low end is n × d.lo (SYS-42). With `early`
|
|
672
|
+
* (SYS-45), the last failed request can start up to one turn before the window closes. Its low end
|
|
673
|
+
* is then the low end of `end` plus n × d.lo. The end band opens one turn before the band end.
|
|
651
674
|
*/
|
|
652
|
-
declare const
|
|
675
|
+
declare const overshootBand: (end: Band, term: Pick<BacklogTerm, "drain"> & Partial<Pick<BacklogTerm, "slowest" | "early">>, sessions: number) => Band;
|
|
653
676
|
/** A count band is a range of counts of requests. */
|
|
654
677
|
interface CountBand {
|
|
655
678
|
readonly lo: number;
|
|
@@ -660,9 +683,10 @@ interface CountBand {
|
|
|
660
683
|
* request each turn until the window closes. With n sessions on the target, the window closes up to
|
|
661
684
|
* n × d.hi after the band end (`backlogEnd`). Thus one session fails 0 to ceil(n × d.hi / turn)
|
|
662
685
|
* requests in the drain. The turn is the mean period of a client (`mean`) times its sessions
|
|
663
|
-
* (`connections`). The term r is not in this band.
|
|
686
|
+
* (`connections`). The term r is not in this band. With `slowest` (SYS-45), the window closes up to
|
|
687
|
+
* (n − 1) × d.hi + `slowest` after the band end. Thus one session fails up to that time over the turn.
|
|
664
688
|
*/
|
|
665
|
-
declare const drainBand: (term: Pick<BacklogTerm, "drain"
|
|
689
|
+
declare const drainBand: (term: Pick<BacklogTerm, "drain"> & Partial<Pick<BacklogTerm, "slowest">>, mean: Quantity, connections: number, sessions: number) => CountBand;
|
|
666
690
|
/**
|
|
667
691
|
* This function gives the failed requests that the backlog term predicts (`BacklogTerm`). Each of
|
|
668
692
|
* the n sessions on the target gets a request each turn. The turn is the measured mean period of a
|
|
@@ -672,7 +696,7 @@ declare const drainBand: (term: Pick<BacklogTerm, "drain">, mean: Quantity, conn
|
|
|
672
696
|
*
|
|
673
697
|
* A term with `drains` (SYS-43) also adds the drain failures of each session (`drainBand`).
|
|
674
698
|
*/
|
|
675
|
-
declare const requestBand: (term: Pick<BacklogTerm, "requests"> & Partial<Pick<BacklogTerm, "drain" | "drains">>, span: Quantity, mean: Quantity, connections: number, sessions: number) => CountBand;
|
|
699
|
+
declare const requestBand: (term: Pick<BacklogTerm, "requests"> & Partial<Pick<BacklogTerm, "drain" | "drains" | "slowest">>, span: Quantity, mean: Quantity, connections: number, sessions: number) => CountBand;
|
|
676
700
|
//#endregion
|
|
677
701
|
//#region src/names.d.ts
|
|
678
702
|
/** These are the ports of the app: its server, and its health server for the probes. */
|
|
@@ -686,11 +710,6 @@ declare const CLIENT = "client";
|
|
|
686
710
|
declare const REDIS = "redis";
|
|
687
711
|
//#endregion
|
|
688
712
|
//#region src/observe.d.ts
|
|
689
|
-
/**
|
|
690
|
-
* This module reads a run from its lines. Each time is in milliseconds on CLOCK_MONOTONIC. All the
|
|
691
|
-
* containers of the VM share that clock: the clients, the service, the agents, the injector, the
|
|
692
|
-
* watcher and the prober.
|
|
693
|
-
*/
|
|
694
713
|
/**
|
|
695
714
|
* A line is one JSON line of a source of a run, with its stamp `t` in milliseconds on
|
|
696
715
|
* CLOCK_MONOTONIC. It is a request of a client, a record of the service, a line of grpc-go or a probe answer. It is
|
|
@@ -1296,16 +1315,23 @@ declare const readRecord: (data: unknown) => KindCellRecord;
|
|
|
1296
1315
|
//#region src/stats.d.ts
|
|
1297
1316
|
/** This fraction, δ_rel, is how far the median of a cell can be outside its band and stay equivalent. */
|
|
1298
1317
|
declare const RELATIVE = .05;
|
|
1299
|
-
/**
|
|
1318
|
+
/**
|
|
1319
|
+
* This function gives the median of sorted values: the middle value, or the mean of the two middle values.
|
|
1320
|
+
* It is `median` of @mark1russell7/rigor-statistics, which throws a RangeError for an empty list.
|
|
1321
|
+
*/
|
|
1300
1322
|
declare const middle: (sorted: readonly number[]) => number;
|
|
1301
|
-
/**
|
|
1323
|
+
/**
|
|
1324
|
+
* This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). It is
|
|
1325
|
+
* `quantileSorted` of @mark1russell7/rigor-statistics with the method `"nearest-rank"`.
|
|
1326
|
+
*/
|
|
1302
1327
|
declare const quantileOf: (sorted: readonly number[], p: number) => number;
|
|
1303
1328
|
/**
|
|
1304
1329
|
* This function gives the distribution-free interval of a median: [x_(k), x_(n+1−k)], for the
|
|
1305
1330
|
* largest k whose two tails each hold 2.5 % or less. For eleven runs, it gives [x_(2), x_(10)],
|
|
1306
|
-
* at 98.8 %.
|
|
1331
|
+
* at 98.8 %. It is `medianInterval` of @mark1russell7/rigor-statistics at the level 0.95. An
|
|
1332
|
+
* empty list throws a RangeError.
|
|
1307
1333
|
*/
|
|
1308
1334
|
declare const medianInterval: (sorted: readonly number[]) => [number, number];
|
|
1309
1335
|
//#endregion
|
|
1310
|
-
export { unitOf as $,
|
|
1311
|
-
//# sourceMappingURL=judge-
|
|
1336
|
+
export { unitOf as $, scenario as $n, REDIS as $t, TriggerV1 as A, Template as An, recordsOf as At, RunCheck as B, KubeProxyMode as Bn, sliceReadyAt as Bt, KindCellResult as C, PodSettings as Cn, intakeOf as Ct, PredictionV1 as D, Replica as Dn, periodOf as Dt, LoadSample as E, Reference as En, outcomesOf as Et, KIND_NOISE as F, DATAPLANES as Fn, sessionsAt as Ft, factsOf as G, ZONE_LOST as Gn, transitionOf as Gt, checkRun as H, NodeImage as Hn, slicesOf as Ht, KindDecision as I, Dataplane as In, signalOf as It, observationEnd as J, goDuration as Jn, ztunnelReplaced as Jt, judgeKind as K, cidrOverlap as Kn, tunnelsOf as Kt, KindVerdict as L, KUBE_PROXY_MODES as Ln, signalsOf as Lt, upgrade as M, TriggerKind as Mn, restartOf as Mt, upgradeCell as N, WindowPrediction as Nn, restartsAt as Nt, RunCheckV1 as O, ResetReuse as On, podsAt as Ot, Deleted as P, Workload as Pn, rulesOf as Pt, reusesReset as Q, nodeNames as Qn, PORT as Qt, LAST_SLACK as R, KindConfig as Rn, sliceDropOf as Rt, KindCellRecordV1 as S, NonePrediction as Sn, failuresOf as St, KindVerdictV1 as T, RedisDeclaration as Tn, kernelCounts as Tt, cyclesOf as U, ZONE_KEPT as Un, socketsOf as Ut, RunFacts as V, NODE_IMAGES as Vn, sliceReadyOf as Vt, deletionsOf as W, ZONE_LABEL as Wn, stoppingOf as Wt, propagationSource as X, kindConfig as Xn, HEALTH_PORT as Xt, propagationOf as Y, isKubeProxyMode as Yn, CLIENT as Yt, referenceOf as Z, kubeProxyPatch as Zn, LOG_LABEL as Zt, ClusterManifest as _, KindRun as _n, byClients as _t, STAGES as a, overshootBand as an, PodLine as at, FORMAT_V1 as b, MeshFlavor as bn, dropOf as bt, readRecord as c, secondsOf as cn, Request as ct, calibrationOf as d, Band as dn, SliceLine as dt, SERVER as en, scenarioProblems as er, updatesOf as et, cellsTable as f, Cycle as fn, SocketLine as ft, BandV1 as g, KindCell as gn, backendsAt as gt, timeSpread as h, Flap as hn, ZtunnelPodLine as ht, quantileOf as i, drainBand as in, Period as it, judge as j, Trigger as jn, requestsOf as jt, RunFactsV1 as k, Stack as kn, podsOf as kt, Judged as l, showBand as ln, RulesLine as lt, predictionText as m, EdgeProtocol as mn, TunnelLine as mt, medianInterval as n, backlogEnd as nn, HBONE_PORT as nt, kindCellRecordSchema as o, requestBand as on, PropagationSource as ot, medianText as p, Declaration as pn, TCP_STATE as pt, observationAfter as q, cidrRange as qn, ztunnelPodsOf as qt, middle as r, bandOf as rn, Line as rt, kindCellRecordV1Schema as s, seconds as sn, RecordLine as st, RELATIVE as t, CountBand as tn, zoneOf as tr, Endpoint as tt, TimeSpread as u, BacklogTerm as un, Sessions as ut, EnvironmentManifest as v, KubeletProbe as vn, byNode as vt, KindCellV1 as w, Prediction as wn, isTunnelState as wt, KindCellRecord as x, MeshMode as xn, emptyOf as xt, FORMAT as y, Mesh as yn, deletionOf as yt, Propagated as z, KindScenario as zn, sliceEmptyOf as zt };
|
|
1337
|
+
//# sourceMappingURL=judge-B_wVAwjx.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { format, valueIn } from "@mark1russell7/quantity";
|
|
2
|
+
import { median, medianInterval, quantileSorted } from "@mark1russell7/rigor-statistics";
|
|
2
3
|
import { extentSchema, quantitySchema } from "@mark1russell7/quantity/schema";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
//#region src/bands.ts
|
|
@@ -26,13 +27,38 @@ const showBand = (band) => {
|
|
|
26
27
|
/** This function rounds a time to the microsecond, thus a band has no float residue. */
|
|
27
28
|
const us = (value) => Math.round(value * 1e6) / 1e6;
|
|
28
29
|
/**
|
|
30
|
+
* This function gives the largest time after the band end at which the window of n sessions closes,
|
|
31
|
+
* in seconds. Each session drains in d, thus it is n × d.hi. With `slowest` (SYS-45), one of the n
|
|
32
|
+
* sessions can drain up to that time, thus it is (n − 1) × d.hi + the larger of `slowest` and d.hi.
|
|
33
|
+
*/
|
|
34
|
+
const closingOf = (term, sessions) => {
|
|
35
|
+
const hi = valueIn(term.drain.hi, "s");
|
|
36
|
+
if (term.slowest === void 0 || sessions < 1) return sessions * hi;
|
|
37
|
+
return (sessions - 1) * hi + Math.max(valueIn(term.slowest, "s"), hi);
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
29
40
|
* This function gives the end band of a window with the backlog term (`BacklogTerm`). It adds n × d
|
|
30
41
|
* to each end of `end`, the end band without the term. The value n is the sessions on the target.
|
|
42
|
+
* A term with `slowest` (SYS-45) adds (n − 1) × d.hi + `slowest` to the high end instead.
|
|
31
43
|
*/
|
|
32
44
|
const backlogEnd = (end, term, sessions) => {
|
|
33
45
|
const ends = secondsOf(end);
|
|
34
46
|
const drain = secondsOf(term.drain);
|
|
35
|
-
return bandOf(us(ends.lo + sessions * drain.lo), us(ends.hi + sessions
|
|
47
|
+
return bandOf(us(ends.lo + sessions * drain.lo), us(ends.hi + closingOf(term, sessions)));
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* This function gives the band of the start of the last failed request of a window with the backlog
|
|
51
|
+
* term, from the band end (the high end of `end`). This is the overshoot of a run. Its high end is
|
|
52
|
+
* the high end of `backlogEnd`. Without `early`, its low end is n × d.lo (SYS-42). With `early`
|
|
53
|
+
* (SYS-45), the last failed request can start up to one turn before the window closes. Its low end
|
|
54
|
+
* is then the low end of `end` plus n × d.lo. The end band opens one turn before the band end.
|
|
55
|
+
*/
|
|
56
|
+
const overshootBand = (end, term, sessions) => {
|
|
57
|
+
const ends = secondsOf(end);
|
|
58
|
+
const closes = secondsOf(backlogEnd(end, term, sessions));
|
|
59
|
+
const drain = secondsOf(term.drain);
|
|
60
|
+
const lo = term.early === true ? closes.lo - ends.hi : sessions * drain.lo;
|
|
61
|
+
return bandOf(us(lo), us(closes.hi - ends.hi));
|
|
36
62
|
};
|
|
37
63
|
/** This function gives a count rounded to six places, thus 10 s / 20 ms gives 500 and not 499.99999. */
|
|
38
64
|
const counted = (value) => Math.round(value * 1e6) / 1e6;
|
|
@@ -47,13 +73,14 @@ const turnOf = (mean, connections) => {
|
|
|
47
73
|
* request each turn until the window closes. With n sessions on the target, the window closes up to
|
|
48
74
|
* n × d.hi after the band end (`backlogEnd`). Thus one session fails 0 to ceil(n × d.hi / turn)
|
|
49
75
|
* requests in the drain. The turn is the mean period of a client (`mean`) times its sessions
|
|
50
|
-
* (`connections`). The term r is not in this band.
|
|
76
|
+
* (`connections`). The term r is not in this band. With `slowest` (SYS-45), the window closes up to
|
|
77
|
+
* (n − 1) × d.hi + `slowest` after the band end. Thus one session fails up to that time over the turn.
|
|
51
78
|
*/
|
|
52
79
|
const drainBand = (term, mean, connections, sessions) => {
|
|
53
80
|
const turn = turnOf(mean, connections);
|
|
54
81
|
return {
|
|
55
82
|
lo: 0,
|
|
56
|
-
hi: Math.ceil(counted(
|
|
83
|
+
hi: Math.ceil(counted(closingOf(term, sessions) / turn))
|
|
57
84
|
};
|
|
58
85
|
};
|
|
59
86
|
/**
|
|
@@ -69,7 +96,10 @@ const requestBand = (term, span, mean, connections, sessions) => {
|
|
|
69
96
|
const turn = turnOf(mean, connections);
|
|
70
97
|
const each = counted(valueIn(span, "s") / turn);
|
|
71
98
|
if (term.drains === true && term.drain === void 0) throw new RangeError("a term with drains has no drain time d");
|
|
72
|
-
const drained = term.drains === true ? drainBand({
|
|
99
|
+
const drained = term.drains === true ? drainBand({
|
|
100
|
+
drain: term.drain,
|
|
101
|
+
slowest: term.slowest
|
|
102
|
+
}, mean, connections, sessions) : {
|
|
73
103
|
lo: 0,
|
|
74
104
|
hi: 0
|
|
75
105
|
};
|
|
@@ -90,7 +120,36 @@ const SERVER = "lab";
|
|
|
90
120
|
const CLIENT = "client";
|
|
91
121
|
const REDIS = "redis";
|
|
92
122
|
//#endregion
|
|
123
|
+
//#region src/stats.ts
|
|
124
|
+
/** This fraction, δ_rel, is how far the median of a cell can be outside its band and stay equivalent. */
|
|
125
|
+
const RELATIVE = .05;
|
|
126
|
+
/**
|
|
127
|
+
* This function gives the median of sorted values: the middle value, or the mean of the two middle values.
|
|
128
|
+
* It is `median` of @mark1russell7/rigor-statistics, which throws a RangeError for an empty list.
|
|
129
|
+
*/
|
|
130
|
+
const middle = (sorted) => median(sorted);
|
|
131
|
+
/**
|
|
132
|
+
* This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). It is
|
|
133
|
+
* `quantileSorted` of @mark1russell7/rigor-statistics with the method `"nearest-rank"`.
|
|
134
|
+
*/
|
|
135
|
+
const quantileOf = (sorted, p) => quantileSorted(sorted, p, "nearest-rank");
|
|
136
|
+
/**
|
|
137
|
+
* This function gives the distribution-free interval of a median: [x_(k), x_(n+1−k)], for the
|
|
138
|
+
* largest k whose two tails each hold 2.5 % or less. For eleven runs, it gives [x_(2), x_(10)],
|
|
139
|
+
* at 98.8 %. It is `medianInterval` of @mark1russell7/rigor-statistics at the level 0.95. An
|
|
140
|
+
* empty list throws a RangeError.
|
|
141
|
+
*/
|
|
142
|
+
const medianInterval$1 = (sorted) => {
|
|
143
|
+
const interval = medianInterval(sorted, .95);
|
|
144
|
+
return [interval.low, interval.high];
|
|
145
|
+
};
|
|
146
|
+
//#endregion
|
|
93
147
|
//#region src/observe.ts
|
|
148
|
+
/**
|
|
149
|
+
* This module reads a run from its lines. Each time is in milliseconds on CLOCK_MONOTONIC. All the
|
|
150
|
+
* containers of the VM share that clock: the clients, the service, the agents, the injector, the
|
|
151
|
+
* watcher and the prober.
|
|
152
|
+
*/
|
|
94
153
|
/** This port is the HBONE port of ztunnel in each pod of the ambient mesh of Istio 1.31.3: the mesh leg ends there. */
|
|
95
154
|
const HBONE_PORT = 15008;
|
|
96
155
|
/** These are the states of a TCP socket of Linux that a tunnel line names (include/net/tcp_states.h of Linux v6.17, lines 12–28). */
|
|
@@ -152,10 +211,6 @@ const sessionsAt = (lines, at, target, connections) => {
|
|
|
152
211
|
byClient
|
|
153
212
|
};
|
|
154
213
|
};
|
|
155
|
-
const medianOf = (sorted) => {
|
|
156
|
-
const middle = Math.floor(sorted.length / 2);
|
|
157
|
-
return sorted.length % 2 === 1 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
|
|
158
|
-
};
|
|
159
214
|
/**
|
|
160
215
|
* This function gives the measured period of the clients from their request lines that start from
|
|
161
216
|
* `from` to `to`. The timer of a client is late by a different amount at each tick. Thus the median
|
|
@@ -181,12 +236,12 @@ const periodOf = (lines, from, to) => {
|
|
|
181
236
|
const intervals = mine.slice(1).map((t, at) => t - mine[at]);
|
|
182
237
|
span += mine.at(-1) - mine[0];
|
|
183
238
|
all.push(...intervals);
|
|
184
|
-
byClient[client] =
|
|
239
|
+
byClient[client] = middle(intervals.sort((a, b) => a - b));
|
|
185
240
|
}
|
|
186
241
|
if (all.length === 0) return null;
|
|
187
242
|
all.sort((a, b) => a - b);
|
|
188
243
|
return {
|
|
189
|
-
median:
|
|
244
|
+
median: middle(all),
|
|
190
245
|
mean: span / all.length,
|
|
191
246
|
low: all[0],
|
|
192
247
|
high: all.at(-1),
|
|
@@ -295,38 +350,6 @@ const restartsAt = (lines, at) => {
|
|
|
295
350
|
return out;
|
|
296
351
|
};
|
|
297
352
|
//#endregion
|
|
298
|
-
//#region src/stats.ts
|
|
299
|
-
/** This fraction, δ_rel, is how far the median of a cell can be outside its band and stay equivalent. */
|
|
300
|
-
const RELATIVE = .05;
|
|
301
|
-
/** This function gives the median of sorted values: the middle value, or the mean of the two middle values. */
|
|
302
|
-
const middle = (sorted) => {
|
|
303
|
-
const half = Math.floor(sorted.length / 2);
|
|
304
|
-
return sorted.length % 2 === 1 ? sorted[half] : (sorted[half - 1] + sorted[half]) / 2;
|
|
305
|
-
};
|
|
306
|
-
/** This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). */
|
|
307
|
-
const quantileOf = (sorted, p) => sorted[Math.min(sorted.length, Math.max(1, Math.ceil(p * sorted.length))) - 1];
|
|
308
|
-
/** This function gives P(X ≤ j) for X ~ Binomial(n, 1/2), exactly. */
|
|
309
|
-
const below = (n, j) => {
|
|
310
|
-
let term = 1;
|
|
311
|
-
let sum = 0;
|
|
312
|
-
for (let i = 0; i <= j; i += 1) {
|
|
313
|
-
sum += term;
|
|
314
|
-
term = term * (n - i) / (i + 1);
|
|
315
|
-
}
|
|
316
|
-
return sum / 2 ** n;
|
|
317
|
-
};
|
|
318
|
-
/**
|
|
319
|
-
* This function gives the distribution-free interval of a median: [x_(k), x_(n+1−k)], for the
|
|
320
|
-
* largest k whose two tails each hold 2.5 % or less. For eleven runs, it gives [x_(2), x_(10)],
|
|
321
|
-
* at 98.8 %.
|
|
322
|
-
*/
|
|
323
|
-
const medianInterval = (sorted) => {
|
|
324
|
-
const n = sorted.length;
|
|
325
|
-
let k = 0;
|
|
326
|
-
while (k + 1 <= n / 2 && below(n, k) <= .025) k += 1;
|
|
327
|
-
return k === 0 ? [sorted[0], sorted[n - 1]] : [sorted[k - 1], sorted[n - k]];
|
|
328
|
-
};
|
|
329
|
-
//#endregion
|
|
330
353
|
//#region src/verdict.ts
|
|
331
354
|
/**
|
|
332
355
|
* This time is δ for kind: each time of a run lands in its band ± δ. Its parts are the interval of
|
|
@@ -482,7 +505,8 @@ const windowOf = (prediction) => prediction.kind === "window" ? prediction : pre
|
|
|
482
505
|
const observationAfter = (cell) => {
|
|
483
506
|
const window = windowOf(cell.prediction);
|
|
484
507
|
if (window === null || window.end === null) return null;
|
|
485
|
-
const
|
|
508
|
+
const backlog = window.backlog;
|
|
509
|
+
const drained = backlog === void 0 ? 0 : backlog.slowest === void 0 || backlog.most < 1 ? backlog.most * valueIn(backlog.drain.hi, "ms") : (backlog.most - 1) * valueIn(backlog.drain.hi, "ms") + Math.max(valueIn(backlog.slowest, "ms"), valueIn(backlog.drain.hi, "ms"));
|
|
486
510
|
return seconds(sec(valueIn(window.end.band.hi, "ms") + drained + valueIn(cell.workload.timeout, "ms") + NOISE));
|
|
487
511
|
};
|
|
488
512
|
/**
|
|
@@ -1171,7 +1195,7 @@ const judgeKind = (cell, runs) => {
|
|
|
1171
1195
|
};
|
|
1172
1196
|
if (band !== null && values.length > 0) {
|
|
1173
1197
|
const ends = secondsOf(band);
|
|
1174
|
-
const [from, to] = medianInterval(values);
|
|
1198
|
+
const [from, to] = medianInterval$1(values);
|
|
1175
1199
|
const wide = {
|
|
1176
1200
|
lo: ends.lo * .95,
|
|
1177
1201
|
hi: ends.hi * 1.05
|
|
@@ -1236,6 +1260,15 @@ const upgradeTrigger = (trigger) => {
|
|
|
1236
1260
|
}
|
|
1237
1261
|
};
|
|
1238
1262
|
};
|
|
1263
|
+
/** The format `/1` has no backlog term, but its type does. Each time of the term is in seconds. */
|
|
1264
|
+
const upgradeBacklog = (backlog) => {
|
|
1265
|
+
const { slowest, ...rest } = backlog;
|
|
1266
|
+
return {
|
|
1267
|
+
...rest,
|
|
1268
|
+
drain: band(backlog.drain),
|
|
1269
|
+
...slowest === void 0 ? {} : { slowest: seconds(slowest) }
|
|
1270
|
+
};
|
|
1271
|
+
};
|
|
1239
1272
|
const upgradeWindow = (window) => {
|
|
1240
1273
|
const { afterReset, propagation, backlog, ...rest } = window;
|
|
1241
1274
|
return {
|
|
@@ -1253,10 +1286,7 @@ const upgradeWindow = (window) => {
|
|
|
1253
1286
|
outcome: afterReset.outcome
|
|
1254
1287
|
} },
|
|
1255
1288
|
...propagation === void 0 ? {} : { propagation: band(propagation) },
|
|
1256
|
-
...backlog === void 0 ? {} : { backlog:
|
|
1257
|
-
...backlog,
|
|
1258
|
-
drain: band(backlog.drain)
|
|
1259
|
-
} }
|
|
1289
|
+
...backlog === void 0 ? {} : { backlog: upgradeBacklog(backlog) }
|
|
1260
1290
|
};
|
|
1261
1291
|
};
|
|
1262
1292
|
const upgradePrediction = (prediction) => {
|
|
@@ -1385,8 +1415,7 @@ const judge = (record) => {
|
|
|
1385
1415
|
const timeSpread = (times) => {
|
|
1386
1416
|
if (times.length === 0) return null;
|
|
1387
1417
|
const sorted = times.map((each) => valueIn(each, "s")).sort((a, b) => a - b);
|
|
1388
|
-
const
|
|
1389
|
-
const median = sorted.length % 2 === 1 ? sorted[half] : (sorted[half - 1] + sorted[half]) / 2;
|
|
1418
|
+
const median = middle(sorted);
|
|
1390
1419
|
return {
|
|
1391
1420
|
count: sorted.length,
|
|
1392
1421
|
min: seconds(sorted[0]),
|
|
@@ -1404,7 +1433,7 @@ const atBand = (from, band) => {
|
|
|
1404
1433
|
const predictionText = (prediction) => {
|
|
1405
1434
|
switch (prediction.kind) {
|
|
1406
1435
|
case "none": return prediction.outcomes === void 0 ? "no failure" : `no ${prediction.outcomes.join(", ")}`;
|
|
1407
|
-
case "window": return `failures only from ${atBand(prediction.start.from, prediction.start.band)}${prediction.end === null ? "" : ` to ${atBand(prediction.end.from, prediction.end.band)}`}${prediction.each === true ? ", of each deleted replica" : ""}${prediction.flaps === true ? ", in each cycle" : ""}${prediction.nodes === "paused" ? ", on the paused node" : ""}${prediction.certain ? ", at least one" : ""}${prediction.outcomes === void 0 ? "" : `, each one ${prediction.outcomes.join(" or ")}`}${prediction.afterReset === void 0 ? "" : `, or a ${prediction.afterReset.outcome} up to ${format(prediction.afterReset.life)} after a reset on its port`}${prediction.propagation === void 0 ? "" : `, the rules drop the replica in ${showBand(prediction.propagation)}`}${prediction.backlog === void 0 ? "" : `, the end n × ${showBand(prediction.backlog.drain)} later and ${prediction.backlog.requests.lo}–${prediction.backlog.requests.hi} more failures for each of the n sessions on the target${prediction.backlog.drains === true ? ", and its failures each turn in the drain of the n sessions" : ""}, counted at the measured period`}`;
|
|
1436
|
+
case "window": return `failures only from ${atBand(prediction.start.from, prediction.start.band)}${prediction.end === null ? "" : ` to ${atBand(prediction.end.from, prediction.end.band)}`}${prediction.each === true ? ", of each deleted replica" : ""}${prediction.flaps === true ? ", in each cycle" : ""}${prediction.nodes === "paused" ? ", on the paused node" : ""}${prediction.certain ? ", at least one" : ""}${prediction.outcomes === void 0 ? "" : `, each one ${prediction.outcomes.join(" or ")}`}${prediction.afterReset === void 0 ? "" : `, or a ${prediction.afterReset.outcome} up to ${format(prediction.afterReset.life)} after a reset on its port`}${prediction.propagation === void 0 ? "" : `, the rules drop the replica in ${showBand(prediction.propagation)}`}${prediction.backlog === void 0 ? "" : `, the end n × ${showBand(prediction.backlog.drain)} later and ${prediction.backlog.requests.lo}–${prediction.backlog.requests.hi} more failures for each of the n sessions on the target${prediction.backlog.drains === true ? ", and its failures each turn in the drain of the n sessions" : ""}, counted at the measured period${prediction.backlog.slowest === void 0 ? "" : `, one session draining up to ${format(prediction.backlog.slowest)}`}${prediction.backlog.early === true ? ", the last failure up to one turn before the end" : ""}`}`;
|
|
1408
1437
|
case "removal": return `Service empty in ${showBand(prediction.band)}${prediction.flaps === true ? " after each fault, and ready again before the next" : ""}${prediction.window === void 0 ? "" : `; ${predictionText(prediction.window)}`}`;
|
|
1409
1438
|
case "leaves": return `the replica leaves in ${showBand(prediction.band)}${prediction.window === void 0 ? "" : `; ${predictionText(prediction.window)}`}`;
|
|
1410
1439
|
case "restarts": return prediction.band === null ? "no restart" : `each replica SIGTERM in ${showBand(prediction.band)}`;
|
|
@@ -1711,7 +1740,9 @@ const recordOf = (a, main) => {
|
|
|
1711
1740
|
hi: count
|
|
1712
1741
|
}),
|
|
1713
1742
|
most: count,
|
|
1714
|
-
drains: z.boolean().optional()
|
|
1743
|
+
drains: z.boolean().optional(),
|
|
1744
|
+
slowest: a.optional(),
|
|
1745
|
+
early: z.boolean().optional()
|
|
1715
1746
|
}).optional(),
|
|
1716
1747
|
why: z.string()
|
|
1717
1748
|
});
|
|
@@ -1938,6 +1969,6 @@ const readRecord = (data) => {
|
|
|
1938
1969
|
throw new Error(`a kind cell record has the format ${FORMAT} or ${FORMAT_V1}, not ${String(format)}`);
|
|
1939
1970
|
};
|
|
1940
1971
|
//#endregion
|
|
1941
|
-
export {
|
|
1972
|
+
export { signalsOf as $, HBONE_PORT as A, isTunnelState as B, observationEnd as C, drainBand as Ct, reusesReset as D, secondsOf as Dt, referenceOf as E, seconds as Et, deletionOf as F, podsOf as G, outcomesOf as H, dropOf as I, restartOf as J, recordsOf as K, emptyOf as L, backendsAt as M, byClients as N, unitOf as O, showBand as Ot, byNode as P, signalOf as Q, failuresOf as R, observationAfter as S, bandOf as St, propagationSource as T, requestBand as Tt, periodOf as U, kernelCounts as V, podsAt as W, rulesOf as X, restartsAt as Y, sessionsAt as Z, checkRun as _, LOG_LABEL as _t, calibrationOf as a, socketsOf as at, factsOf as b, SERVER as bt, predictionText as c, tunnelsOf as ct, FORMAT_V1 as d, RELATIVE as dt, sliceDropOf as et, judge as f, medianInterval$1 as ft, LAST_SLACK as g, HEALTH_PORT as gt, KIND_NOISE as h, CLIENT as ht, readRecord as i, slicesOf as it, TCP_STATE as j, updatesOf as k, timeSpread as l, ztunnelPodsOf as lt, upgradeCell as m, quantileOf as mt, kindCellRecordSchema as n, sliceReadyAt as nt, cellsTable as o, stoppingOf as ot, upgrade as p, middle as pt, requestsOf as q, kindCellRecordV1Schema as r, sliceReadyOf as rt, medianText as s, transitionOf as st, STAGES as t, sliceEmptyOf as tt, FORMAT as u, ztunnelReplaced as ut, cyclesOf as v, PORT as vt, propagationOf as w, overshootBand as wt, judgeKind as x, backlogEnd as xt, deletionsOf as y, REDIS as yt, intakeOf as z };
|
|
1942
1973
|
|
|
1943
|
-
//# sourceMappingURL=judge-
|
|
1974
|
+
//# sourceMappingURL=judge-Bc84w-no.js.map
|