@mark1russell7/service 0.5.10 → 0.5.12
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 +18 -1
- package/build/{builder-DyDB7zM9.d.ts → builder-DawJhq4p.d.ts} +3 -3
- package/build/{clock-D-38uH_z.d.ts → clock-mVqhXD0b.d.ts} +2 -2
- package/build/clock.d.ts +1 -1
- package/build/clock.js +11 -3
- package/build/clock.js.map +1 -1
- package/build/core-C2wnF4mg.d.ts +183 -0
- package/build/heartbeat.d.ts +1 -1
- package/build/http.d.ts +2 -2
- package/build/index.d.ts +13 -8
- package/build/index.js +416 -250
- package/build/index.js.map +1 -1
- package/build/{lifecycle-Chu9Pri2.d.ts → lifecycle-fgYfxrHK.d.ts} +18 -3
- package/build/{limiter-DCDdzVwe.d.ts → limiter-B0849Vhp.d.ts} +2 -2
- package/build/limiter.d.ts +2 -2
- package/build/machine-Czfb6fV4.js +372 -0
- package/build/machine-Czfb6fV4.js.map +1 -0
- package/build/pg.d.ts +230 -0
- package/build/pg.js +534 -0
- package/build/pg.js.map +1 -0
- package/build/redis.d.ts +26 -139
- package/build/redis.js +72 -279
- package/build/redis.js.map +1 -1
- package/build/{store-DzTyosou.d.ts → store-D5HLgBnW.d.ts} +2 -2
- package/build/testing.d.ts +3 -3
- package/package.json +11 -3
package/build/index.js
CHANGED
|
@@ -720,6 +720,248 @@ const compilePattern = (pattern) => {
|
|
|
720
720
|
};
|
|
721
721
|
};
|
|
722
722
|
//#endregion
|
|
723
|
+
//#region src/units.ts
|
|
724
|
+
/** This function gives the cause of an abort as text. */
|
|
725
|
+
const causeOf = (signal) => signal.reason instanceof Error ? signal.reason.message : String(signal.reason ?? "the unit got an abort");
|
|
726
|
+
/**
|
|
727
|
+
* This function does one unit of work, and gives its end. With a request, the unit goes through
|
|
728
|
+
* `life.request`, thus the service counts it, drains it and can cut it. A throw after the abort of
|
|
729
|
+
* the transport is a cut, not a failure (S6 A10). A throw after the bound is a failure.
|
|
730
|
+
*/
|
|
731
|
+
const runUnit = async (run) => {
|
|
732
|
+
const { clock, bound, abort, life, request, unit, work } = run;
|
|
733
|
+
const timeout = new AbortController();
|
|
734
|
+
const cancel = Number.isFinite(bound) ? clock.after(bound, () => timeout.abort(/* @__PURE__ */ new Error(`the unit did not end in its unit_processing_time of ${bound} ms`))) : () => {};
|
|
735
|
+
const call = async (tracker) => work(AbortSignal.any(tracker === void 0 ? [abort.signal, timeout.signal] : [
|
|
736
|
+
abort.signal,
|
|
737
|
+
timeout.signal,
|
|
738
|
+
tracker
|
|
739
|
+
]));
|
|
740
|
+
const thrown = (error) => {
|
|
741
|
+
if (abort.signal.aborted) return {
|
|
742
|
+
kind: "cut",
|
|
743
|
+
cause: causeOf(abort.signal),
|
|
744
|
+
retryable: false
|
|
745
|
+
};
|
|
746
|
+
if (timeout.signal.aborted) return {
|
|
747
|
+
kind: "failed",
|
|
748
|
+
error: timeout.signal.reason
|
|
749
|
+
};
|
|
750
|
+
return {
|
|
751
|
+
kind: "failed",
|
|
752
|
+
error
|
|
753
|
+
};
|
|
754
|
+
};
|
|
755
|
+
try {
|
|
756
|
+
if (request === void 0) try {
|
|
757
|
+
return {
|
|
758
|
+
kind: "done",
|
|
759
|
+
value: await call()
|
|
760
|
+
};
|
|
761
|
+
} catch (error) {
|
|
762
|
+
return thrown(error);
|
|
763
|
+
}
|
|
764
|
+
let collected;
|
|
765
|
+
try {
|
|
766
|
+
const route = typeof request.route === "string" ? request.route : request.route(unit);
|
|
767
|
+
const detail = request.detail?.(unit);
|
|
768
|
+
collected = life.request(request.controller, route, (signal) => call(signal).then((value) => ({ value })), detail === void 0 ? {} : { detail }).collect();
|
|
769
|
+
} catch (error) {
|
|
770
|
+
return {
|
|
771
|
+
kind: "failed",
|
|
772
|
+
error
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
const { items, end } = await collected;
|
|
776
|
+
if (end.kind === "done") return {
|
|
777
|
+
kind: "done",
|
|
778
|
+
value: items[0]?.value
|
|
779
|
+
};
|
|
780
|
+
if (end.kind === "failed") return thrown(end.error);
|
|
781
|
+
if (end.kind === "refused") return {
|
|
782
|
+
kind: "refused",
|
|
783
|
+
cause: end.cause
|
|
784
|
+
};
|
|
785
|
+
return {
|
|
786
|
+
kind: "cut",
|
|
787
|
+
cause: end.cause,
|
|
788
|
+
retryable: end.retryable
|
|
789
|
+
};
|
|
790
|
+
} finally {
|
|
791
|
+
cancel();
|
|
792
|
+
}
|
|
793
|
+
};
|
|
794
|
+
/** This function makes a flight set on a clock. */
|
|
795
|
+
const flights = (clock) => {
|
|
796
|
+
const units = /* @__PURE__ */ new Set();
|
|
797
|
+
const idle = /* @__PURE__ */ new Set();
|
|
798
|
+
const lower = /* @__PURE__ */ new Set();
|
|
799
|
+
let aborted = null;
|
|
800
|
+
const settle = () => {
|
|
801
|
+
for (const done of [...lower]) done();
|
|
802
|
+
lower.clear();
|
|
803
|
+
if (units.size === 0) for (const done of [...idle]) done();
|
|
804
|
+
};
|
|
805
|
+
const abort = (reason) => {
|
|
806
|
+
aborted ??= { reason };
|
|
807
|
+
for (const unit of [...units]) if (!unit.signal.aborted) unit.abort(aborted.reason);
|
|
808
|
+
};
|
|
809
|
+
return {
|
|
810
|
+
get size() {
|
|
811
|
+
return units.size;
|
|
812
|
+
},
|
|
813
|
+
add(unit) {
|
|
814
|
+
units.add(unit);
|
|
815
|
+
if (aborted !== null && !unit.signal.aborted) unit.abort(aborted.reason);
|
|
816
|
+
return () => {
|
|
817
|
+
if (units.delete(unit)) settle();
|
|
818
|
+
};
|
|
819
|
+
},
|
|
820
|
+
abort,
|
|
821
|
+
clear() {
|
|
822
|
+
units.clear();
|
|
823
|
+
settle();
|
|
824
|
+
},
|
|
825
|
+
drain(deadline, signal) {
|
|
826
|
+
const cooperative = () => abort(signal.reason);
|
|
827
|
+
if (signal.aborted) cooperative();
|
|
828
|
+
else signal.addEventListener("abort", cooperative, { once: true });
|
|
829
|
+
if (units.size === 0 || deadline <= clock.now()) {
|
|
830
|
+
signal.removeEventListener("abort", cooperative);
|
|
831
|
+
return Promise.resolve();
|
|
832
|
+
}
|
|
833
|
+
return new Promise((resolve) => {
|
|
834
|
+
let cancel = () => {};
|
|
835
|
+
const done = () => {
|
|
836
|
+
idle.delete(done);
|
|
837
|
+
cancel();
|
|
838
|
+
signal.removeEventListener("abort", cooperative);
|
|
839
|
+
resolve();
|
|
840
|
+
};
|
|
841
|
+
idle.add(done);
|
|
842
|
+
cancel = clock.after(Math.max(0, deadline - clock.now()), done);
|
|
843
|
+
});
|
|
844
|
+
},
|
|
845
|
+
less() {
|
|
846
|
+
return new Promise((resolve) => lower.add(resolve));
|
|
847
|
+
},
|
|
848
|
+
release() {
|
|
849
|
+
for (const done of [...lower]) done();
|
|
850
|
+
lower.clear();
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
};
|
|
854
|
+
/** This function makes a sleeper on a clock. */
|
|
855
|
+
const sleeper = (clock) => {
|
|
856
|
+
let wakes = 0;
|
|
857
|
+
let stopped = false;
|
|
858
|
+
const sleeps = /* @__PURE__ */ new Set();
|
|
859
|
+
const backoffs = /* @__PURE__ */ new Set();
|
|
860
|
+
const wait = (ms, into) => stopped ? Promise.resolve() : new Promise((resolve) => {
|
|
861
|
+
let cancel = () => {};
|
|
862
|
+
const done = () => {
|
|
863
|
+
if (!into.delete(done)) return;
|
|
864
|
+
cancel();
|
|
865
|
+
resolve();
|
|
866
|
+
};
|
|
867
|
+
into.add(done);
|
|
868
|
+
if (Number.isFinite(ms)) cancel = clock.after(ms, done);
|
|
869
|
+
});
|
|
870
|
+
return {
|
|
871
|
+
get wakes() {
|
|
872
|
+
return wakes;
|
|
873
|
+
},
|
|
874
|
+
sleep(ms, since) {
|
|
875
|
+
if (since !== wakes) return Promise.resolve();
|
|
876
|
+
return wait(ms, sleeps);
|
|
877
|
+
},
|
|
878
|
+
backoff(ms) {
|
|
879
|
+
return wait(ms, backoffs);
|
|
880
|
+
},
|
|
881
|
+
wake() {
|
|
882
|
+
wakes += 1;
|
|
883
|
+
const ended = sleeps.size;
|
|
884
|
+
for (const done of [...sleeps]) done();
|
|
885
|
+
return ended;
|
|
886
|
+
},
|
|
887
|
+
stop() {
|
|
888
|
+
stopped = true;
|
|
889
|
+
for (const done of [...sleeps, ...backoffs]) done();
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
};
|
|
893
|
+
/** This function waits for a work until a bound on the clock, in milliseconds. */
|
|
894
|
+
const settleWithin = (clock, ms, work) => new Promise((resolve) => {
|
|
895
|
+
const cancel = Number.isFinite(ms) ? clock.after(ms, () => resolve({ kind: "bound" })) : () => {};
|
|
896
|
+
work.then(() => {
|
|
897
|
+
cancel();
|
|
898
|
+
resolve({ kind: "done" });
|
|
899
|
+
}, (error) => {
|
|
900
|
+
cancel();
|
|
901
|
+
resolve({
|
|
902
|
+
kind: "failed",
|
|
903
|
+
error
|
|
904
|
+
});
|
|
905
|
+
});
|
|
906
|
+
});
|
|
907
|
+
/**
|
|
908
|
+
* This function gives the value of a promise, or `stop` when the signal aborts first. Each wait adds
|
|
909
|
+
* its own listener, and removes it when the promise settles. A race against one pending promise
|
|
910
|
+
* keeps each settled value until that promise ends.
|
|
911
|
+
*/
|
|
912
|
+
const untilAbort = (promise, signal, stop) => {
|
|
913
|
+
if (signal.aborted) return Promise.race([promise, Promise.resolve(stop)]);
|
|
914
|
+
return new Promise((resolve, reject) => {
|
|
915
|
+
const onAbort = () => resolve(stop);
|
|
916
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
917
|
+
promise.then((value) => {
|
|
918
|
+
signal.removeEventListener("abort", onAbort);
|
|
919
|
+
resolve(value);
|
|
920
|
+
}, (error) => {
|
|
921
|
+
signal.removeEventListener("abort", onAbort);
|
|
922
|
+
reject(error);
|
|
923
|
+
});
|
|
924
|
+
});
|
|
925
|
+
};
|
|
926
|
+
/**
|
|
927
|
+
* This function gives the backoff of the knobs of a loop. The first delay is `retry_base`, and each
|
|
928
|
+
* delay is two times longer, up to `retry_cap`. Each delay has a jitter up to the base, as in the Redis client.
|
|
929
|
+
*/
|
|
930
|
+
const retryOf = (knobs, owner) => {
|
|
931
|
+
const base = boundedMillisecondsOf(knobs, "retry_base", owner);
|
|
932
|
+
const backoff = {
|
|
933
|
+
base,
|
|
934
|
+
factor: 2,
|
|
935
|
+
cap: boundedMillisecondsOf(knobs, "retry_cap", owner),
|
|
936
|
+
jitter: {
|
|
937
|
+
kind: "add",
|
|
938
|
+
amount: base
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
const problems = backoffProblems(backoff);
|
|
942
|
+
if (problems.length > 0) throw new Error(`${owner}: the retry_base and retry_cap give no backoff: ${problems.join(", ")}`);
|
|
943
|
+
return backoff;
|
|
944
|
+
};
|
|
945
|
+
/**
|
|
946
|
+
* This function gives the problems of the bounds of a loop in a declaration. The close bound fits
|
|
947
|
+
* in the cap of `close transports`. The bound of a unit fits in the cap of `drain`, or the drain can cut a unit (S6 A10).
|
|
948
|
+
*/
|
|
949
|
+
const boundProblems = (owner, closeBound, unitBound, description) => {
|
|
950
|
+
const capOf = (name) => {
|
|
951
|
+
const phase = description.shutdown.phases.find((each) => each.name === name);
|
|
952
|
+
return phase === void 0 ? void 0 : valueIn(phase.cap, "ms");
|
|
953
|
+
};
|
|
954
|
+
const found = [];
|
|
955
|
+
const close = capOf("close transports");
|
|
956
|
+
if (close === void 0) found.push(`${owner} needs the phase "close transports" to close`);
|
|
957
|
+
else if (closeBound >= close) found.push(`the close_bound of ${owner}, ${closeBound} ms, does not fit in the cap of "close transports", ${close} ms`);
|
|
958
|
+
const drain = capOf("drain");
|
|
959
|
+
if (drain === void 0) found.push(`${owner} needs the phase "drain" to end its units`);
|
|
960
|
+
else if (!Number.isFinite(unitBound)) found.push(`the unit_processing_time of ${owner} has no bound, thus the drain can cut a unit at its cap of ${drain} ms`);
|
|
961
|
+
else if (unitBound >= drain) found.push(`the unit_processing_time of ${owner}, ${unitBound} ms, does not fit in the cap of "drain", ${drain} ms`);
|
|
962
|
+
return found;
|
|
963
|
+
};
|
|
964
|
+
//#endregion
|
|
723
965
|
//#region src/requests.ts
|
|
724
966
|
const isAsyncIterable$1 = (value) => value !== null && (typeof value === "object" || typeof value === "function") && typeof value[Symbol.asyncIterator] === "function";
|
|
725
967
|
const isPromiseLike = (value) => value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
@@ -815,10 +1057,8 @@ const tracker = (controllers, clock, refuses, choices = /* @__PURE__ */ new Map(
|
|
|
815
1057
|
let returned = false;
|
|
816
1058
|
let source = null;
|
|
817
1059
|
let unary = null;
|
|
818
|
-
|
|
819
|
-
const
|
|
820
|
-
interrupt = () => resolve("interrupted");
|
|
821
|
-
});
|
|
1060
|
+
const interruption = new AbortController();
|
|
1061
|
+
const interrupt = () => interruption.abort();
|
|
822
1062
|
const cutEnd = (cause) => {
|
|
823
1063
|
const since = quantity(Math.max(0, clock.now() - started) / 1e3, "s");
|
|
824
1064
|
const retryable = mayReissue(operation, since);
|
|
@@ -887,7 +1127,7 @@ const tracker = (controllers, clock, refuses, choices = /* @__PURE__ */ new Map(
|
|
|
887
1127
|
}
|
|
888
1128
|
const next = async () => {
|
|
889
1129
|
if (ended) return null;
|
|
890
|
-
if (end === null) await
|
|
1130
|
+
if (end === null) await untilAbort(ready, interruption.signal, "interrupted");
|
|
891
1131
|
if (end === null && unary !== null) {
|
|
892
1132
|
const { value } = unary;
|
|
893
1133
|
unary = null;
|
|
@@ -905,7 +1145,7 @@ const tracker = (controllers, clock, refuses, choices = /* @__PURE__ */ new Map(
|
|
|
905
1145
|
const pending = source.next();
|
|
906
1146
|
let step;
|
|
907
1147
|
try {
|
|
908
|
-
step = await Promise.
|
|
1148
|
+
step = await untilAbort(Promise.resolve(pending), interruption.signal, "interrupted");
|
|
909
1149
|
} catch (error) {
|
|
910
1150
|
failed(error);
|
|
911
1151
|
step = "interrupted";
|
|
@@ -1416,6 +1656,25 @@ const watchdog = (clock, spec, trace) => {
|
|
|
1416
1656
|
const isTime$1 = (amount) => convertible(amount.unit, "s");
|
|
1417
1657
|
const above = (amount) => amount.value === "infinite" || isTime$1(amount) && valueIn(amount, "s") > 0;
|
|
1418
1658
|
const whole = (count) => Number.isInteger(count) && count >= 1;
|
|
1659
|
+
/** This function copies a check, with its poll and the loops that mark it. */
|
|
1660
|
+
const copyCheck = (check) => ({
|
|
1661
|
+
...check,
|
|
1662
|
+
poll: { ...check.poll },
|
|
1663
|
+
...check.marks === void 0 ? {} : { marks: {
|
|
1664
|
+
loops: [...check.marks.loops],
|
|
1665
|
+
stall: { ...check.marks.stall }
|
|
1666
|
+
} }
|
|
1667
|
+
});
|
|
1668
|
+
/** This function gives the problems of the loops that mark a check. `lint()` compares the stall time with the loops. */
|
|
1669
|
+
const marksProblems = (check) => {
|
|
1670
|
+
const marks = check.marks;
|
|
1671
|
+
if (marks === void 0) return [];
|
|
1672
|
+
const problems = [];
|
|
1673
|
+
if (check.step !== "progress") problems.push(`check ${check.name} names the loops that mark it, but its step is ${check.step}, not progress`);
|
|
1674
|
+
if (marks.loops.length === 0) problems.push(`check ${check.name} names no loop that marks it`);
|
|
1675
|
+
if (typeof marks.stall.value !== "number" || !above(marks.stall)) problems.push(`check ${check.name} has a stall time that is not a time above zero`);
|
|
1676
|
+
return problems;
|
|
1677
|
+
};
|
|
1419
1678
|
/** This function gives the problems of a timing: a zero interval or count fails decoding. */
|
|
1420
1679
|
const timingProblems = (policy, timing) => {
|
|
1421
1680
|
if (timing.type === "debounce") {
|
|
@@ -1604,14 +1863,11 @@ const service = (name) => {
|
|
|
1604
1863
|
check(check, run) {
|
|
1605
1864
|
once(checks, check.name, "check");
|
|
1606
1865
|
if (started && run === void 0) throw new Error(`check ${check.name} joins after the start, thus it needs its function`);
|
|
1607
|
-
checks.push(
|
|
1866
|
+
checks.push(copyCheck(check));
|
|
1608
1867
|
if (run !== void 0) runs.set(check.name, run);
|
|
1609
1868
|
if (started) {
|
|
1610
1869
|
partial = true;
|
|
1611
|
-
live?.addCheck(
|
|
1612
|
-
...check,
|
|
1613
|
-
poll: { ...check.poll }
|
|
1614
|
-
}, run);
|
|
1870
|
+
live?.addCheck(copyCheck(check), run);
|
|
1615
1871
|
}
|
|
1616
1872
|
return builder;
|
|
1617
1873
|
},
|
|
@@ -1749,6 +2005,7 @@ const service = (name) => {
|
|
|
1749
2005
|
if (!isTime$1(check.poll.interval) || !isTime$1(check.poll.timeout)) problems.push(`check ${check.name} polls in a unit that is not a time`);
|
|
1750
2006
|
else if (!above(check.poll.interval) || !above(check.poll.timeout)) problems.push(`check ${check.name} polls with an interval or a timeout that is not above zero`);
|
|
1751
2007
|
if (!(check.poll.jitter >= 0 && check.poll.jitter < 1)) problems.push(`check ${check.name} has a jitter of ${check.poll.jitter}, not a fraction below 1`);
|
|
2008
|
+
problems.push(...marksProblems(check));
|
|
1752
2009
|
const timing = check.gates === null ? null : policies[check.gates];
|
|
1753
2010
|
if (timing?.type === "debounce" && isTime$1(check.poll.interval) && above(timing.interval) && valueIn(check.poll.interval, "s") !== valueIn(timing.interval, "s")) problems.push(`check ${check.name} polls every ${valueIn(check.poll.interval, "s")} s, but the ${check.gates} debounce counts polls every ${valueIn(timing.interval, "s")} s`);
|
|
1754
2011
|
}
|
|
@@ -1791,10 +2048,7 @@ const service = (name) => {
|
|
|
1791
2048
|
operations: { ...entry.operations }
|
|
1792
2049
|
})),
|
|
1793
2050
|
controllers: controllersOut,
|
|
1794
|
-
checks: checks.map(
|
|
1795
|
-
...entry,
|
|
1796
|
-
poll: { ...entry.poll }
|
|
1797
|
-
})),
|
|
2051
|
+
checks: checks.map(copyCheck),
|
|
1798
2052
|
...limiters.length === 0 ? {} : { limiters: limiters.map((entry) => ({
|
|
1799
2053
|
...entry,
|
|
1800
2054
|
policy: { ...entry.policy },
|
|
@@ -1901,10 +2155,16 @@ const marginOf = (inequality, index, bind) => {
|
|
|
1901
2155
|
if (typeof bind.margin === "number") return bind.margin;
|
|
1902
2156
|
return typeof inequality.margin === "number" ? inequality.margin : 0;
|
|
1903
2157
|
};
|
|
2158
|
+
/** This function tells if an inequality reads a symbol with no limit: "inf", "off" or an infinite number. */
|
|
2159
|
+
const readsAbsent = (inequality, bind) => [...inequality.lhs.terms, ...inequality.rhs.terms].some((term) => {
|
|
2160
|
+
const bound = boundOf$1(bind, keyOf(term));
|
|
2161
|
+
return bound !== void 0 && value(bound) === Infinity;
|
|
2162
|
+
});
|
|
1904
2163
|
/**
|
|
1905
2164
|
* This function evaluates each inequality on one binding. "<" holds when lhs + margin < rhs, and
|
|
1906
2165
|
* ">" holds when lhs > rhs + margin. Only the inequalities with all their symbols bound apply.
|
|
1907
|
-
* The others are null.
|
|
2166
|
+
* The others are null. Absent timers can leave no order: the same infinity on each side, or both
|
|
2167
|
+
* signs of infinity on one side. Then the inequality holds only because a timer is absent.
|
|
1908
2168
|
*/
|
|
1909
2169
|
const evaluate = (rule, bind) => inequalities(rule).map((inequality, index) => {
|
|
1910
2170
|
const lhs = sideOf(inequality.lhs, bind);
|
|
@@ -1916,6 +2176,12 @@ const evaluate = (rule, bind) => inequalities(rule).map((inequality, index) => {
|
|
|
1916
2176
|
margin,
|
|
1917
2177
|
holds: null
|
|
1918
2178
|
};
|
|
2179
|
+
if ((Number.isNaN(lhs) || Number.isNaN(rhs) || lhs === rhs && !Number.isFinite(lhs)) && readsAbsent(inequality, bind)) return {
|
|
2180
|
+
lhs,
|
|
2181
|
+
rhs,
|
|
2182
|
+
margin,
|
|
2183
|
+
holds: true
|
|
2184
|
+
};
|
|
1919
2185
|
return {
|
|
1920
2186
|
lhs,
|
|
1921
2187
|
rhs,
|
|
@@ -1934,13 +2200,7 @@ const verdictOf = (rule, bind, evaluated) => {
|
|
|
1934
2200
|
if (applicable.length === 0) return "depends";
|
|
1935
2201
|
if (applicable.some((index) => evaluated[index]?.holds === false)) return "violated";
|
|
1936
2202
|
const all = inequalities(rule);
|
|
1937
|
-
return applicable.some((index) =>
|
|
1938
|
-
const inequality = all[index];
|
|
1939
|
-
return [...inequality.lhs.terms, ...inequality.rhs.terms].some((term) => {
|
|
1940
|
-
const bound = boundOf$1(bind, keyOf(term));
|
|
1941
|
-
return bound !== void 0 && value(bound) === Infinity;
|
|
1942
|
-
});
|
|
1943
|
-
}) ? "unbounded" : "holds";
|
|
2203
|
+
return applicable.some((index) => readsAbsent(all[index], bind)) ? "unbounded" : "holds";
|
|
1944
2204
|
};
|
|
1945
2205
|
//#endregion
|
|
1946
2206
|
//#region src/lint.ts
|
|
@@ -2139,14 +2399,144 @@ const declarationFindings = (svc) => svc.shutdown.onRepeatSignal === void 0 ? [{
|
|
|
2139
2399
|
evaluated: [],
|
|
2140
2400
|
unbound: ["shutdown.onRepeatSignal"]
|
|
2141
2401
|
}] : [];
|
|
2402
|
+
/** This identifier is the rule of the findings about the stall time of a progress check (`Check.marks`). */
|
|
2403
|
+
const PROGRESS_RULE = "progress";
|
|
2404
|
+
/**
|
|
2405
|
+
* This rule compares the stall time of a progress check with the longest gap between two marks of
|
|
2406
|
+
* the slowest loop that it names. A shorter stall time trips the check while each loop turns on time.
|
|
2407
|
+
*/
|
|
2408
|
+
const PROGRESS_LAW = {
|
|
2409
|
+
id: PROGRESS_RULE,
|
|
2410
|
+
rule: "the stall time of a progress check is at least the longest gap between two marks of the slowest loop that it names",
|
|
2411
|
+
window: "a loop that turns on time can trip the check",
|
|
2412
|
+
expr: {
|
|
2413
|
+
lhs: { terms: [{
|
|
2414
|
+
knob: "stall",
|
|
2415
|
+
coef: 1,
|
|
2416
|
+
at: "check"
|
|
2417
|
+
}] },
|
|
2418
|
+
op: ">=",
|
|
2419
|
+
rhs: { terms: [{
|
|
2420
|
+
knob: "mark_gap",
|
|
2421
|
+
coef: 1,
|
|
2422
|
+
at: "loop"
|
|
2423
|
+
}] },
|
|
2424
|
+
margin: 0
|
|
2425
|
+
}
|
|
2426
|
+
};
|
|
2427
|
+
/** These are the knobs of a worker that bound the gap between two of its marks. */
|
|
2428
|
+
const WORKER_GAP_KNOBS = [
|
|
2429
|
+
"worker_sleep",
|
|
2430
|
+
"unit_processing_time",
|
|
2431
|
+
"retry_base",
|
|
2432
|
+
"retry_cap"
|
|
2433
|
+
];
|
|
2434
|
+
/**
|
|
2435
|
+
* This function gives the longest gap between two marks of each loop with a name. The rule counts
|
|
2436
|
+
* a mark at the end of each turn of the loop, also a turn that fails.
|
|
2437
|
+
* - A check polls on a fixed delay from the start of each poll, and each poll ends at its timeout
|
|
2438
|
+
* at the latest. Thus the gap is `interval × (1 + jitter) + timeout`.
|
|
2439
|
+
* - After an iteration, a lane of a worker waits its sleep, or its backoff after a failure. The
|
|
2440
|
+
* longest backoff is `retry_cap` plus its jitter of up to `retry_base`. The next iteration then
|
|
2441
|
+
* takes up to `unit_processing_time`. Thus the gap is the longer wait plus that bound.
|
|
2442
|
+
*
|
|
2443
|
+
* A sleep or a bound without a limit gives a gap without a limit. An iteration that does not end
|
|
2444
|
+
* at its abort can take more time, and the rule does not bound it.
|
|
2445
|
+
*/
|
|
2446
|
+
const gapsOf = (svc, loop) => {
|
|
2447
|
+
const gaps = svc.checks.filter((check) => check.name === loop).map((check) => ({
|
|
2448
|
+
loop,
|
|
2449
|
+
seconds: secondsOf(check.poll.interval) * (1 + check.poll.jitter) + secondsOf(check.poll.timeout),
|
|
2450
|
+
unbound: []
|
|
2451
|
+
}));
|
|
2452
|
+
for (const worker of svc.transports) {
|
|
2453
|
+
if (worker.kind !== "worker" || worker.name !== loop) continue;
|
|
2454
|
+
const knob = (name) => {
|
|
2455
|
+
const amount = worker.knobs[name];
|
|
2456
|
+
if (amount === void 0 || !isTime(amount.unit)) return void 0;
|
|
2457
|
+
return amount.value === "infinite" ? Infinity : secondsOf(amount);
|
|
2458
|
+
};
|
|
2459
|
+
const unbound = WORKER_GAP_KNOBS.filter((name) => knob(name) === void 0).map((name) => `${loop}.${name}`);
|
|
2460
|
+
if (unbound.length > 0) {
|
|
2461
|
+
gaps.push({
|
|
2462
|
+
loop,
|
|
2463
|
+
seconds: void 0,
|
|
2464
|
+
unbound
|
|
2465
|
+
});
|
|
2466
|
+
continue;
|
|
2467
|
+
}
|
|
2468
|
+
const [sleep, unit, base, cap] = WORKER_GAP_KNOBS.map((name) => knob(name));
|
|
2469
|
+
const backoff = Number.isFinite(base) && Number.isFinite(cap) ? backoffBand({
|
|
2470
|
+
base,
|
|
2471
|
+
factor: 2,
|
|
2472
|
+
cap,
|
|
2473
|
+
jitter: {
|
|
2474
|
+
kind: "add",
|
|
2475
|
+
amount: base
|
|
2476
|
+
}
|
|
2477
|
+
}).high : Infinity;
|
|
2478
|
+
gaps.push({
|
|
2479
|
+
loop,
|
|
2480
|
+
seconds: Math.max(sleep, backoff) + unit,
|
|
2481
|
+
unbound: []
|
|
2482
|
+
});
|
|
2483
|
+
}
|
|
2484
|
+
return gaps;
|
|
2485
|
+
};
|
|
2486
|
+
/**
|
|
2487
|
+
* This function gives the findings of each check that names the loops that mark it. A name that is
|
|
2488
|
+
* not a check or a worker of the service gets a finding of its own, with the verdict `depends`.
|
|
2489
|
+
* Without `marks`, a check gets no finding.
|
|
2490
|
+
*/
|
|
2491
|
+
const progressFindings = (svc) => {
|
|
2492
|
+
const findings = [];
|
|
2493
|
+
const finding = (check, fields) => ({
|
|
2494
|
+
rule: PROGRESS_RULE,
|
|
2495
|
+
scope: check.name,
|
|
2496
|
+
statement: PROGRESS_LAW.rule,
|
|
2497
|
+
window: PROGRESS_LAW.window,
|
|
2498
|
+
...fields
|
|
2499
|
+
});
|
|
2500
|
+
for (const check of svc.checks) {
|
|
2501
|
+
const marks = check.marks;
|
|
2502
|
+
if (marks === void 0) continue;
|
|
2503
|
+
const gaps = [];
|
|
2504
|
+
for (const loop of marks.loops) {
|
|
2505
|
+
const found = gapsOf(svc, loop);
|
|
2506
|
+
if (found.length > 0) gaps.push(...found);
|
|
2507
|
+
else findings.push(finding(check, {
|
|
2508
|
+
verdict: "depends",
|
|
2509
|
+
statement: "each loop that a progress check names is a check or a worker of the service",
|
|
2510
|
+
window: `the check waits for the marks of ${loop}, and the service has no loop with that name`,
|
|
2511
|
+
evaluated: [],
|
|
2512
|
+
unbound: [loop]
|
|
2513
|
+
}));
|
|
2514
|
+
}
|
|
2515
|
+
if (gaps.length === 0) continue;
|
|
2516
|
+
const unbound = [...isTime(marks.stall.unit) ? [] : [`${check.name}.marks.stall`], ...gaps.flatMap((gap) => gap.unbound)];
|
|
2517
|
+
const slowest = gaps.reduce((worst, gap) => (gap.seconds ?? -Infinity) > (worst.seconds ?? -Infinity) ? gap : worst);
|
|
2518
|
+
const bind = {};
|
|
2519
|
+
if (isTime(marks.stall.unit)) bind["stall@check"] = boundOf(marks.stall);
|
|
2520
|
+
if (unbound.length === 0 && slowest.seconds !== void 0) bind["mark_gap@loop"] = Number.isFinite(slowest.seconds) ? slowest.seconds : "inf";
|
|
2521
|
+
const evaluated = evaluate(PROGRESS_LAW, bind);
|
|
2522
|
+
findings.push(finding(check, {
|
|
2523
|
+
verdict: verdictOf(PROGRESS_LAW, bind, evaluated),
|
|
2524
|
+
...unbound.length === 0 ? { statement: `${PROGRESS_LAW.rule} (${slowest.loop})` } : {},
|
|
2525
|
+
evaluated,
|
|
2526
|
+
unbound
|
|
2527
|
+
}));
|
|
2528
|
+
}
|
|
2529
|
+
return findings;
|
|
2530
|
+
};
|
|
2142
2531
|
/**
|
|
2143
2532
|
* This function applies each service rule to a declaration and a scenario. A rule applies one time
|
|
2144
2533
|
* for the service, for each client, for each consumer and worker, or for each limiter. The function
|
|
2145
2534
|
* also gives a finding for each necessary field that the description does not give (`DECLARATION_RULE`).
|
|
2535
|
+
* Each progress check that names its loops also gets its findings (`PROGRESS_RULE`).
|
|
2146
2536
|
*/
|
|
2147
2537
|
const lint = (svc, scenario, rules) => {
|
|
2148
2538
|
const service = serviceBindings(svc, scenario).bind;
|
|
2149
|
-
const findings = [...declarationFindings(svc)];
|
|
2539
|
+
const findings = [...declarationFindings(svc), ...progressFindings(svc)];
|
|
2150
2540
|
for (const rule of rules) {
|
|
2151
2541
|
if (!SERVICE_RULES.includes(rule.id)) continue;
|
|
2152
2542
|
const symbols = symbolsOf(rule);
|
|
@@ -2296,229 +2686,6 @@ const kubernetes = (pod) => {
|
|
|
2296
2686
|
};
|
|
2297
2687
|
};
|
|
2298
2688
|
//#endregion
|
|
2299
|
-
//#region src/units.ts
|
|
2300
|
-
/** This function gives the cause of an abort as text. */
|
|
2301
|
-
const causeOf = (signal) => signal.reason instanceof Error ? signal.reason.message : String(signal.reason ?? "the unit got an abort");
|
|
2302
|
-
/**
|
|
2303
|
-
* This function does one unit of work, and gives its end. With a request, the unit goes through
|
|
2304
|
-
* `life.request`, thus the service counts it, drains it and can cut it. A throw after the abort of
|
|
2305
|
-
* the transport is a cut, not a failure (S6 A10). A throw after the bound is a failure.
|
|
2306
|
-
*/
|
|
2307
|
-
const runUnit = async (run) => {
|
|
2308
|
-
const { clock, bound, abort, life, request, unit, work } = run;
|
|
2309
|
-
const timeout = new AbortController();
|
|
2310
|
-
const cancel = Number.isFinite(bound) ? clock.after(bound, () => timeout.abort(/* @__PURE__ */ new Error(`the unit did not end in its unit_processing_time of ${bound} ms`))) : () => {};
|
|
2311
|
-
const call = async (tracker) => work(AbortSignal.any(tracker === void 0 ? [abort.signal, timeout.signal] : [
|
|
2312
|
-
abort.signal,
|
|
2313
|
-
timeout.signal,
|
|
2314
|
-
tracker
|
|
2315
|
-
]));
|
|
2316
|
-
const thrown = (error) => {
|
|
2317
|
-
if (abort.signal.aborted) return {
|
|
2318
|
-
kind: "cut",
|
|
2319
|
-
cause: causeOf(abort.signal),
|
|
2320
|
-
retryable: false
|
|
2321
|
-
};
|
|
2322
|
-
if (timeout.signal.aborted) return {
|
|
2323
|
-
kind: "failed",
|
|
2324
|
-
error: timeout.signal.reason
|
|
2325
|
-
};
|
|
2326
|
-
return {
|
|
2327
|
-
kind: "failed",
|
|
2328
|
-
error
|
|
2329
|
-
};
|
|
2330
|
-
};
|
|
2331
|
-
try {
|
|
2332
|
-
if (request === void 0) try {
|
|
2333
|
-
return {
|
|
2334
|
-
kind: "done",
|
|
2335
|
-
value: await call()
|
|
2336
|
-
};
|
|
2337
|
-
} catch (error) {
|
|
2338
|
-
return thrown(error);
|
|
2339
|
-
}
|
|
2340
|
-
let collected;
|
|
2341
|
-
try {
|
|
2342
|
-
const route = typeof request.route === "string" ? request.route : request.route(unit);
|
|
2343
|
-
const detail = request.detail?.(unit);
|
|
2344
|
-
collected = life.request(request.controller, route, (signal) => call(signal).then((value) => ({ value })), detail === void 0 ? {} : { detail }).collect();
|
|
2345
|
-
} catch (error) {
|
|
2346
|
-
return {
|
|
2347
|
-
kind: "failed",
|
|
2348
|
-
error
|
|
2349
|
-
};
|
|
2350
|
-
}
|
|
2351
|
-
const { items, end } = await collected;
|
|
2352
|
-
if (end.kind === "done") return {
|
|
2353
|
-
kind: "done",
|
|
2354
|
-
value: items[0]?.value
|
|
2355
|
-
};
|
|
2356
|
-
if (end.kind === "failed") return thrown(end.error);
|
|
2357
|
-
if (end.kind === "refused") return {
|
|
2358
|
-
kind: "refused",
|
|
2359
|
-
cause: end.cause
|
|
2360
|
-
};
|
|
2361
|
-
return {
|
|
2362
|
-
kind: "cut",
|
|
2363
|
-
cause: end.cause,
|
|
2364
|
-
retryable: end.retryable
|
|
2365
|
-
};
|
|
2366
|
-
} finally {
|
|
2367
|
-
cancel();
|
|
2368
|
-
}
|
|
2369
|
-
};
|
|
2370
|
-
/** This function makes a flight set on a clock. */
|
|
2371
|
-
const flights = (clock) => {
|
|
2372
|
-
const units = /* @__PURE__ */ new Set();
|
|
2373
|
-
const idle = /* @__PURE__ */ new Set();
|
|
2374
|
-
const lower = /* @__PURE__ */ new Set();
|
|
2375
|
-
let aborted = null;
|
|
2376
|
-
const settle = () => {
|
|
2377
|
-
for (const done of [...lower]) done();
|
|
2378
|
-
lower.clear();
|
|
2379
|
-
if (units.size === 0) for (const done of [...idle]) done();
|
|
2380
|
-
};
|
|
2381
|
-
const abort = (reason) => {
|
|
2382
|
-
aborted ??= { reason };
|
|
2383
|
-
for (const unit of [...units]) if (!unit.signal.aborted) unit.abort(aborted.reason);
|
|
2384
|
-
};
|
|
2385
|
-
return {
|
|
2386
|
-
get size() {
|
|
2387
|
-
return units.size;
|
|
2388
|
-
},
|
|
2389
|
-
add(unit) {
|
|
2390
|
-
units.add(unit);
|
|
2391
|
-
if (aborted !== null && !unit.signal.aborted) unit.abort(aborted.reason);
|
|
2392
|
-
return () => {
|
|
2393
|
-
if (units.delete(unit)) settle();
|
|
2394
|
-
};
|
|
2395
|
-
},
|
|
2396
|
-
abort,
|
|
2397
|
-
clear() {
|
|
2398
|
-
units.clear();
|
|
2399
|
-
settle();
|
|
2400
|
-
},
|
|
2401
|
-
drain(deadline, signal) {
|
|
2402
|
-
const cooperative = () => abort(signal.reason);
|
|
2403
|
-
if (signal.aborted) cooperative();
|
|
2404
|
-
else signal.addEventListener("abort", cooperative, { once: true });
|
|
2405
|
-
if (units.size === 0 || deadline <= clock.now()) {
|
|
2406
|
-
signal.removeEventListener("abort", cooperative);
|
|
2407
|
-
return Promise.resolve();
|
|
2408
|
-
}
|
|
2409
|
-
return new Promise((resolve) => {
|
|
2410
|
-
let cancel = () => {};
|
|
2411
|
-
const done = () => {
|
|
2412
|
-
idle.delete(done);
|
|
2413
|
-
cancel();
|
|
2414
|
-
signal.removeEventListener("abort", cooperative);
|
|
2415
|
-
resolve();
|
|
2416
|
-
};
|
|
2417
|
-
idle.add(done);
|
|
2418
|
-
cancel = clock.after(Math.max(0, deadline - clock.now()), done);
|
|
2419
|
-
});
|
|
2420
|
-
},
|
|
2421
|
-
less() {
|
|
2422
|
-
return new Promise((resolve) => lower.add(resolve));
|
|
2423
|
-
},
|
|
2424
|
-
release() {
|
|
2425
|
-
for (const done of [...lower]) done();
|
|
2426
|
-
lower.clear();
|
|
2427
|
-
}
|
|
2428
|
-
};
|
|
2429
|
-
};
|
|
2430
|
-
/** This function makes a sleeper on a clock. */
|
|
2431
|
-
const sleeper = (clock) => {
|
|
2432
|
-
let wakes = 0;
|
|
2433
|
-
let stopped = false;
|
|
2434
|
-
const sleeps = /* @__PURE__ */ new Set();
|
|
2435
|
-
const backoffs = /* @__PURE__ */ new Set();
|
|
2436
|
-
const wait = (ms, into) => stopped ? Promise.resolve() : new Promise((resolve) => {
|
|
2437
|
-
let cancel = () => {};
|
|
2438
|
-
const done = () => {
|
|
2439
|
-
if (!into.delete(done)) return;
|
|
2440
|
-
cancel();
|
|
2441
|
-
resolve();
|
|
2442
|
-
};
|
|
2443
|
-
into.add(done);
|
|
2444
|
-
if (Number.isFinite(ms)) cancel = clock.after(ms, done);
|
|
2445
|
-
});
|
|
2446
|
-
return {
|
|
2447
|
-
get wakes() {
|
|
2448
|
-
return wakes;
|
|
2449
|
-
},
|
|
2450
|
-
sleep(ms, since) {
|
|
2451
|
-
if (since !== wakes) return Promise.resolve();
|
|
2452
|
-
return wait(ms, sleeps);
|
|
2453
|
-
},
|
|
2454
|
-
backoff(ms) {
|
|
2455
|
-
return wait(ms, backoffs);
|
|
2456
|
-
},
|
|
2457
|
-
wake() {
|
|
2458
|
-
wakes += 1;
|
|
2459
|
-
const ended = sleeps.size;
|
|
2460
|
-
for (const done of [...sleeps]) done();
|
|
2461
|
-
return ended;
|
|
2462
|
-
},
|
|
2463
|
-
stop() {
|
|
2464
|
-
stopped = true;
|
|
2465
|
-
for (const done of [...sleeps, ...backoffs]) done();
|
|
2466
|
-
}
|
|
2467
|
-
};
|
|
2468
|
-
};
|
|
2469
|
-
/** This function waits for a work until a bound on the clock, in milliseconds. */
|
|
2470
|
-
const settleWithin = (clock, ms, work) => new Promise((resolve) => {
|
|
2471
|
-
const cancel = Number.isFinite(ms) ? clock.after(ms, () => resolve({ kind: "bound" })) : () => {};
|
|
2472
|
-
work.then(() => {
|
|
2473
|
-
cancel();
|
|
2474
|
-
resolve({ kind: "done" });
|
|
2475
|
-
}, (error) => {
|
|
2476
|
-
cancel();
|
|
2477
|
-
resolve({
|
|
2478
|
-
kind: "failed",
|
|
2479
|
-
error
|
|
2480
|
-
});
|
|
2481
|
-
});
|
|
2482
|
-
});
|
|
2483
|
-
/**
|
|
2484
|
-
* This function gives the backoff of the knobs of a loop. The first delay is `retry_base`, and each
|
|
2485
|
-
* delay is two times longer, up to `retry_cap`. Each delay has a jitter up to the base, as in the Redis client.
|
|
2486
|
-
*/
|
|
2487
|
-
const retryOf = (knobs, owner) => {
|
|
2488
|
-
const base = boundedMillisecondsOf(knobs, "retry_base", owner);
|
|
2489
|
-
const backoff = {
|
|
2490
|
-
base,
|
|
2491
|
-
factor: 2,
|
|
2492
|
-
cap: boundedMillisecondsOf(knobs, "retry_cap", owner),
|
|
2493
|
-
jitter: {
|
|
2494
|
-
kind: "add",
|
|
2495
|
-
amount: base
|
|
2496
|
-
}
|
|
2497
|
-
};
|
|
2498
|
-
const problems = backoffProblems(backoff);
|
|
2499
|
-
if (problems.length > 0) throw new Error(`${owner}: the retry_base and retry_cap give no backoff: ${problems.join(", ")}`);
|
|
2500
|
-
return backoff;
|
|
2501
|
-
};
|
|
2502
|
-
/**
|
|
2503
|
-
* This function gives the problems of the bounds of a loop in a declaration. The close bound fits
|
|
2504
|
-
* in the cap of `close transports`. The bound of a unit fits in the cap of `drain`, or the drain can cut a unit (S6 A10).
|
|
2505
|
-
*/
|
|
2506
|
-
const boundProblems = (owner, closeBound, unitBound, description) => {
|
|
2507
|
-
const capOf = (name) => {
|
|
2508
|
-
const phase = description.shutdown.phases.find((each) => each.name === name);
|
|
2509
|
-
return phase === void 0 ? void 0 : valueIn(phase.cap, "ms");
|
|
2510
|
-
};
|
|
2511
|
-
const found = [];
|
|
2512
|
-
const close = capOf("close transports");
|
|
2513
|
-
if (close === void 0) found.push(`${owner} needs the phase "close transports" to close`);
|
|
2514
|
-
else if (closeBound >= close) found.push(`the close_bound of ${owner}, ${closeBound} ms, does not fit in the cap of "close transports", ${close} ms`);
|
|
2515
|
-
const drain = capOf("drain");
|
|
2516
|
-
if (drain === void 0) found.push(`${owner} needs the phase "drain" to end its units`);
|
|
2517
|
-
else if (!Number.isFinite(unitBound)) found.push(`the unit_processing_time of ${owner} has no bound, thus the drain can cut a unit at its cap of ${drain} ms`);
|
|
2518
|
-
else if (unitBound >= drain) found.push(`the unit_processing_time of ${owner}, ${unitBound} ms, does not fit in the cap of "drain", ${drain} ms`);
|
|
2519
|
-
return found;
|
|
2520
|
-
};
|
|
2521
|
-
//#endregion
|
|
2522
2689
|
//#region src/worker.ts
|
|
2523
2690
|
const OWNER$1 = "workerLoop";
|
|
2524
2691
|
/**
|
|
@@ -2706,7 +2873,6 @@ const queueDrain = (knobs, options) => {
|
|
|
2706
2873
|
const running = flights(clock);
|
|
2707
2874
|
const rests = sleeper(clock);
|
|
2708
2875
|
const intake = new AbortController();
|
|
2709
|
-
const stopped = new Promise((resolve) => intake.signal.addEventListener("abort", () => resolve(STOPPED), { once: true }));
|
|
2710
2876
|
const pending = /* @__PURE__ */ new Set();
|
|
2711
2877
|
const active = /* @__PURE__ */ new Set();
|
|
2712
2878
|
let refusals = 0;
|
|
@@ -2861,7 +3027,7 @@ const queueDrain = (knobs, options) => {
|
|
|
2861
3027
|
kind: "error",
|
|
2862
3028
|
error
|
|
2863
3029
|
}));
|
|
2864
|
-
const first = await
|
|
3030
|
+
const first = await untilAbort(taking, intake.signal, STOPPED);
|
|
2865
3031
|
if (first === STOPPED || intake.signal.aborted) {
|
|
2866
3032
|
if (first === STOPPED) taking.then((late) => {
|
|
2867
3033
|
if (late.kind === "job") handBack(late.job);
|
|
@@ -3389,6 +3555,6 @@ const MACHINES = {
|
|
|
3389
3555
|
watchdog: WATCHDOG_MACHINE
|
|
3390
3556
|
};
|
|
3391
3557
|
//#endregion
|
|
3392
|
-
export { DECLARATION_RULE, EXIT_MACHINE, EXIT_SIGNALS, FORMAT, GATE_MACHINE, LATCH_MACHINE, LIMITER_RULES, MACHINES, POLLER_MACHINE, PROCESS_TRIGGERS, SERVICE_RULES, SLIDING_WINDOW_MACHINE, STAGES, TOKEN_BUCKET_MACHINE, WATCHDOG_MACHINE, WINDOW_MACHINE, asDebounce, asWindow, backoffBand, backoffDelay, backoffProblems, capKnob, cooperativeAbortAt, daemon, decide, detectionTime, drainMachine, embeddedProcess, ephemeral, evaluate, failSpan, freeAt, heartbeat, heartbeatDetection, idleSpan, inequalities, isExitCode, isExitSignal, isMessageShape, keyedLimiter, kubernetes, limitRule, limiterMachine, limiterProblems, limiterStateOf, lint, localDev, longestRetryAfter, matchesMessage, mayReissue, memoryStore, nodeProcess, platformClock, processPortOf, queueDrain, realClock, recoverSpan, redeliverOnce, replay, retryAfterSeconds, service, serviceBindings, stageRank, symbolsOf, verdictOf, watchdog, workerLoop };
|
|
3558
|
+
export { DECLARATION_RULE, EXIT_MACHINE, EXIT_SIGNALS, FORMAT, GATE_MACHINE, LATCH_MACHINE, LIMITER_RULES, MACHINES, POLLER_MACHINE, PROCESS_TRIGGERS, PROGRESS_RULE, SERVICE_RULES, SLIDING_WINDOW_MACHINE, STAGES, TOKEN_BUCKET_MACHINE, WATCHDOG_MACHINE, WINDOW_MACHINE, asDebounce, asWindow, backoffBand, backoffDelay, backoffProblems, capKnob, cooperativeAbortAt, daemon, decide, detectionTime, drainMachine, embeddedProcess, ephemeral, evaluate, failSpan, freeAt, heartbeat, heartbeatDetection, idleSpan, inequalities, isExitCode, isExitSignal, isMessageShape, keyedLimiter, kubernetes, limitRule, limiterMachine, limiterProblems, limiterStateOf, lint, localDev, longestRetryAfter, matchesMessage, mayReissue, memoryStore, nodeProcess, platformClock, processPortOf, queueDrain, realClock, recoverSpan, redeliverOnce, replay, retryAfterSeconds, service, serviceBindings, stageRank, symbolsOf, verdictOf, watchdog, workerLoop };
|
|
3393
3559
|
|
|
3394
3560
|
//# sourceMappingURL=index.js.map
|