@oldwhisper/resilience 1.0.3

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 ADDED
@@ -0,0 +1,100 @@
1
+ # Resilience
2
+
3
+ Small resilience wrapper with metrics hooks.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install resilience
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```ts
14
+ import { WrapperInit } from "resilience";
15
+
16
+ function greet(x: number, y: number) {
17
+ return x + y;
18
+ }
19
+
20
+ const metrics = new WrapperInit();
21
+ const resilientGreet = metrics.wrap(greet)
22
+
23
+ const result = resilientGreet(1, 2);
24
+ console.log(result);
25
+ console.log(metrics.functionCalls, metrics.f_store);
26
+ ```
27
+
28
+ ## Core API
29
+
30
+ ### withResilience(fn, config)
31
+
32
+ Wrap any function with retry, timeout, backoff, and circuit breaker support.
33
+
34
+ ```ts
35
+ import { withResilience } from "resilience";
36
+
37
+ const resilient = withResilience(fetchData, {
38
+ name: "fetchData",
39
+ retries: 3,
40
+ timeoutMs: 1000,
41
+ backoff: { type: "fixed", delayMs: 100 },
42
+ hooks: {
43
+ onAttempt: ({ name, attempt }) => console.log(name, attempt),
44
+ },
45
+ });
46
+
47
+ await resilient();
48
+ ```
49
+
50
+ ### WrapperInit
51
+
52
+ Metrics adapter that exposes hooks and a convenience `wrap()` helper.
53
+
54
+ ```ts
55
+ const metrics = new WrapperInit();
56
+ const wrapped = metrics.wrap(task, { retries: 1, timeoutMs: 500 });
57
+ await wrapped();
58
+
59
+ console.log(metrics.functionCalls);
60
+ console.log(metrics.f_store.get("task"));
61
+ ```
62
+
63
+ ## Config
64
+
65
+ ```ts
66
+ type BackoffStrategy =
67
+ | { type: "fixed"; delayMs: number }
68
+ | { type: "exponential"; baseDelayMs: number; maxDelayMs: number; jitter?: boolean }
69
+
70
+ type CircuitBreakerConfig = {
71
+ failureThreshold: number
72
+ resetTimeoutMs: number
73
+ }
74
+
75
+ type ResilienceHooks = {
76
+ onAttempt?: (info: { name: string; attempt: number }) => void
77
+ onSuccess?: (info: { name: string; attempt: number; timeMs: number }) => void
78
+ onFailure?: (info: { name: string; attempt: number; timeMs: number; error: unknown }) => void
79
+ onRetry?: (info: { name: string; attempt: number; delayMs: number; error: unknown }) => void
80
+ onCircuitOpen?: (info: { name: string }) => void
81
+ onCircuitHalfOpen?: (info: { name: string }) => void
82
+ onCircuitClosed?: (info: { name: string }) => void
83
+ }
84
+
85
+ type ResilienceConfig = {
86
+ name?: string
87
+ timeoutMs?: number
88
+ retries?: number
89
+ backoff?: BackoffStrategy
90
+ retryOn?: (err: unknown) => boolean
91
+ circuitBreaker?: CircuitBreakerConfig
92
+ hooks?: ResilienceHooks
93
+ }
94
+ ```
95
+
96
+ ## Notes
97
+
98
+ - `withResilience` returns an async function, even if the original function is sync.
99
+ - Metrics are collected via hooks.
100
+ - If `useAbortSignal: true`, `sleep()` and `resilientFetch()` will be cancelled automatically on timeout.
@@ -0,0 +1,14 @@
1
+ export declare function withResilience<Fn extends (...args: any[]) => any>(fn: Fn, config?: Resilience.ResilienceConfig): (...args: Parameters<Fn>) => Promise<Awaited<ReturnType<Fn>>>;
2
+ export declare const sleep: (ms: number, signal?: AbortSignal | undefined) => Promise<void>;
3
+ export declare const resilientFetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
4
+ export declare class WrapperInit {
5
+ functionCalls: number;
6
+ f_store: Map<string, number>;
7
+ record(name: string): void;
8
+ hooks(): Resilience.ResilienceHooks;
9
+ wrap<Fn extends (...args: any[]) => any>(fn: Fn, config?: Omit<Resilience.ResilienceConfig, "hooks" | "name"> & {
10
+ name?: string;
11
+ }): (...args: Parameters<Fn>) => Promise<Awaited<ReturnType<Fn>>>;
12
+ run<Fn extends (...args: any[]) => any>(fn: Fn, ...args: Parameters<Fn>): ReturnType<Fn>;
13
+ }
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0FA,wBAAgB,cAAc,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAC7D,EAAE,EAAE,EAAE,EACN,MAAM,GAAE,UAAU,CAAC,gBAAqB,GACzC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAoD/D;AAED,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,EAAE,SAAQ,WAAW,GAAG,SAAwB,kBAmB1E,CAAC;AAEP,eAAO,MAAM,cAAc,GAAI,OAAO,WAAW,GAAG,GAAG,EAAE,OAAO,WAAW,sBAI1E,CAAC;AAGF,qBAAa,WAAW;IACpB,aAAa,EAAE,MAAM,CAAI;IACzB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IAEzC,MAAM,CAAC,IAAI,EAAE,MAAM;IAMnB,KAAK,IAAI,UAAU,CAAC,eAAe;IAQnC,IAAI,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACnC,EAAE,EAAE,EAAE,EACN,MAAM,GAAE,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO;IASxF,GAAG,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC;CAW3F"}
package/dist/index.js ADDED
@@ -0,0 +1,199 @@
1
+ /// <reference path="./global.d.ts" />
2
+ let activeSignal;
3
+ async function runWithActiveSignal(signal, fn) {
4
+ const prev = activeSignal;
5
+ activeSignal = signal;
6
+ try {
7
+ return await fn();
8
+ }
9
+ finally {
10
+ activeSignal = prev;
11
+ }
12
+ }
13
+ class CircuitBreaker {
14
+ cfg;
15
+ hooks;
16
+ name;
17
+ state = "CLOSED";
18
+ failures = 0;
19
+ openedAt = 0;
20
+ constructor(cfg, hooks, name = "fn") {
21
+ this.cfg = cfg;
22
+ this.hooks = hooks;
23
+ this.name = name;
24
+ }
25
+ canAttempt() {
26
+ if (this.state === "CLOSED")
27
+ return true;
28
+ const now = Date.now();
29
+ if (this.state === "OPEN" && now - this.openedAt >= this.cfg.resetTimeoutMs) {
30
+ this.state = "HALF_OPEN";
31
+ this.hooks?.onCircuitHalfOpen?.({ name: this.name });
32
+ return true;
33
+ }
34
+ return this.state === "HALF_OPEN";
35
+ }
36
+ onSuccess() {
37
+ if (this.state !== "CLOSED") {
38
+ this.state = "CLOSED";
39
+ this.hooks?.onCircuitClosed?.({ name: this.name });
40
+ }
41
+ this.failures = 0;
42
+ }
43
+ onFailure() {
44
+ this.failures += 1;
45
+ if (this.failures >= this.cfg.failureThreshold) {
46
+ this.state = "OPEN";
47
+ this.openedAt = Date.now();
48
+ this.hooks?.onCircuitOpen?.({ name: this.name });
49
+ }
50
+ }
51
+ }
52
+ function computeBackoffMs(strategy, attempt) {
53
+ if (!strategy)
54
+ return 0;
55
+ if (strategy.type === "fixed")
56
+ return strategy.delayMs;
57
+ const raw = strategy.baseDelayMs * Math.pow(2, Math.max(0, attempt - 1));
58
+ const capped = Math.min(raw, strategy.maxDelayMs);
59
+ if (!strategy.jitter)
60
+ return capped;
61
+ return Math.floor(Math.random() * capped);
62
+ }
63
+ function delay(ms) {
64
+ return new Promise((resolve) => setTimeout(resolve, ms));
65
+ }
66
+ async function withTimeout(p, timeoutMs, controller) {
67
+ if (!timeoutMs)
68
+ return p;
69
+ return await Promise.race([
70
+ p,
71
+ new Promise((_, reject) => setTimeout(() => {
72
+ controller?.abort();
73
+ reject(new Error("TimeoutError"));
74
+ }, timeoutMs)),
75
+ ]);
76
+ }
77
+ export function withResilience(fn, config = {}) {
78
+ const name = config.name ?? fn.name ?? "anonymous";
79
+ const retries = config.retries ?? 0;
80
+ const retryOn = config.retryOn ?? (() => true);
81
+ const hooks = config.hooks;
82
+ const breaker = config.circuitBreaker
83
+ ? new CircuitBreaker(config.circuitBreaker, hooks, name)
84
+ : null;
85
+ return (async (...args) => {
86
+ let lastErr = undefined;
87
+ for (let attempt = 1; attempt <= retries + 1; attempt++) {
88
+ hooks?.onAttempt?.({ name, attempt });
89
+ if (breaker && !breaker.canAttempt()) {
90
+ const e = new Error(`CircuitOpenError: ${name}`);
91
+ lastErr = e;
92
+ throw e;
93
+ }
94
+ const start = Date.now();
95
+ try {
96
+ const controller = config.useAbortSignal ? new AbortController() : undefined;
97
+ const result = await runWithActiveSignal(controller?.signal, async () => {
98
+ const execPromise = Promise.resolve(fn(...args));
99
+ return await withTimeout(execPromise, config.timeoutMs, controller);
100
+ });
101
+ const timeMs = Date.now() - start;
102
+ breaker?.onSuccess();
103
+ hooks?.onSuccess?.({ name, attempt, timeMs });
104
+ return result;
105
+ }
106
+ catch (err) {
107
+ const timeMs = Date.now() - start;
108
+ lastErr = err;
109
+ breaker?.onFailure();
110
+ hooks?.onFailure?.({ name, attempt, timeMs, error: err });
111
+ const shouldRetry = attempt <= retries && retryOn(err);
112
+ if (!shouldRetry)
113
+ throw err;
114
+ const waitMs = computeBackoffMs(config.backoff, attempt);
115
+ hooks?.onRetry?.({ name, attempt, delayMs: waitMs, error: err });
116
+ if (waitMs > 0)
117
+ await delay(waitMs);
118
+ }
119
+ }
120
+ throw lastErr ?? new Error("UnknownError");
121
+ });
122
+ }
123
+ export const sleep = (ms, signal = activeSignal) => new Promise((resolve, reject) => {
124
+ const id = setTimeout(resolve, ms);
125
+ if (!signal)
126
+ return;
127
+ if (signal.aborted) {
128
+ clearTimeout(id);
129
+ reject(new Error("Aborted"));
130
+ return;
131
+ }
132
+ signal.addEventListener("abort", () => {
133
+ clearTimeout(id);
134
+ reject(new Error("Aborted"));
135
+ }, { once: true });
136
+ });
137
+ export const resilientFetch = (input, init) => {
138
+ const signal = init?.signal ?? activeSignal;
139
+ if (!signal)
140
+ return fetch(input, init);
141
+ return fetch(input, { ...init, signal });
142
+ };
143
+ export class WrapperInit {
144
+ functionCalls = 0;
145
+ f_store = new Map();
146
+ record(name) {
147
+ const prev = this.f_store.get(name) ?? 0;
148
+ this.f_store.set(name, prev + 1);
149
+ this.functionCalls++;
150
+ }
151
+ hooks() {
152
+ return {
153
+ onAttempt: ({ name }) => {
154
+ this.record(name);
155
+ },
156
+ };
157
+ }
158
+ wrap(fn, config = {}) {
159
+ return withResilience(fn, {
160
+ ...config,
161
+ name: config.name ?? fn.name ?? "anonymous",
162
+ hooks: this.hooks(),
163
+ });
164
+ }
165
+ run(fn, ...args) {
166
+ const wf = new WrappedFunction(fn, ...args);
167
+ if (!this.f_store.has(wf.name)) {
168
+ this.f_store.set(wf.name, 0);
169
+ }
170
+ const val = wf.run();
171
+ const cur_count = this.f_store.get(wf.name);
172
+ this.f_store.set(wf.name, cur_count + 1);
173
+ this.functionCalls++;
174
+ return val.returnValue;
175
+ }
176
+ }
177
+ class WrappedFunction {
178
+ fn;
179
+ args;
180
+ name;
181
+ constructor(fnPtr, ...args) {
182
+ this.fn = fnPtr;
183
+ this.args = args;
184
+ this.name = fnPtr.name;
185
+ }
186
+ run() {
187
+ const start = Date.now();
188
+ const r_val = this.fn(...this.args);
189
+ const end = Date.now();
190
+ const dif = end - start;
191
+ const res = {
192
+ time: dif,
193
+ returnValue: r_val,
194
+ inputsCount: this.args.length,
195
+ };
196
+ return res;
197
+ }
198
+ }
199
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@oldwhisper/resilience",
3
+ "version": "1.0.3",
4
+ "description": "Resilience wrappers with retries, timeouts, backoff, circuit breaker, and metrics hooks.",
5
+ "main": "./dist/index.ts",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "default": "./dist/index.js"
10
+ }
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.json",
19
+ "prepublishOnly": "npm run build",
20
+ "test": "node -e \"console.log('add tests')\"",
21
+ "start": "node src/index.ts"
22
+ },
23
+ "keywords": [],
24
+ "author": "",
25
+ "license": "ISC",
26
+ "type": "module",
27
+ "devDependencies": {
28
+ "typescript": "^5.9.3"
29
+ }
30
+ }