@rpckit/fallback 0.9.99

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,107 @@
1
+ # @rpckit/fallback
2
+
3
+ Fallback meta-transport for rpckit. Provides automatic failover across multiple transports with optional health-based ranking.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @rpckit/core @rpckit/fallback
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { fallback } from '@rpckit/fallback'
15
+ import { webSocket } from '@rpckit/websocket'
16
+ import { http } from '@rpckit/http'
17
+
18
+ const transport = fallback([
19
+ webSocket('wss://primary.example.com'),
20
+ http('https://backup.example.com'),
21
+ ])
22
+
23
+ await transport.connect()
24
+
25
+ // Automatically tries next transport on failure
26
+ const result = await transport.request('my.method', 'param')
27
+
28
+ await transport.close()
29
+ ```
30
+
31
+ ## Options
32
+
33
+ - `shouldThrow` - `(error: Error) => boolean | undefined` to control fallback behavior per error. Return `true` to throw immediately, `false` to continue to next transport, or `undefined` to use default logic. By default, deterministic JSON-RPC errors (parse error, invalid request, invalid params) stop the fallback chain.
34
+ - `rank` - `true` or `{ interval, sampleCount, timeout, weights, ping }` for health ranking
35
+ - `eagerConnect` - Connect to all transports in parallel (fastest transport is prioritized)
36
+
37
+ ## Health Ranking
38
+
39
+ When `rank` is enabled, transports are periodically pinged and ranked by latency and stability. Requests are routed to the best-performing transport first.
40
+
41
+ **Note:** Without a `ping` function, ranking has no way to probe transport health and will not collect samples — effectively making it a no-op. Provide a `ping` function appropriate for your protocol.
42
+
43
+ ```typescript
44
+ const transport = fallback(transports, {
45
+ rank: {
46
+ interval: 4000, // ms between health checks (default: 4000)
47
+ timeout: 1000, // ping timeout in ms (default: 1000)
48
+ sampleCount: 10, // number of samples to average (default: 10)
49
+ weights: {
50
+ latency: 0.3, // weight for latency score (default: 0.3)
51
+ stability: 0.7, // weight for stability score (default: 0.7)
52
+ },
53
+ ping: (t) => t.request('health.check'), // provide a ping function for your protocol
54
+ },
55
+ })
56
+ ```
57
+
58
+ ### Accessing Scores
59
+
60
+ ```typescript
61
+ // Get current scores
62
+ console.log(transport.scores)
63
+ // [{ transport, score, latency, stability }, ...]
64
+
65
+ // Get ranked transport list
66
+ console.log(transport.transports)
67
+
68
+ // Subscribe to score updates
69
+ const unsub = transport.onScores((scores) => {
70
+ console.log('Scores updated:', scores)
71
+ })
72
+ // Later: unsub()
73
+ ```
74
+
75
+ ## Electrum Cash Variant
76
+
77
+ The `@rpckit/fallback/electrum-cash` subpath provides a variant with `server.ping` as the default ping function for health ranking and a protocol-aware `shouldThrow` that retries on transient server errors (internal error, OOM, warmup, syncing) while stopping on deterministic errors (invalid params, bad address, etc.):
78
+
79
+ ```typescript
80
+ import { fallback } from '@rpckit/fallback/electrum-cash'
81
+ import { webSocket } from '@rpckit/websocket/electrum-cash'
82
+
83
+ const transport = fallback([
84
+ webSocket('wss://server1.example.com:50004'),
85
+ webSocket('wss://server2.example.com:50004'),
86
+ ], { rank: true }) // Uses server.ping for health checks
87
+ ```
88
+
89
+ The `shouldThrow` function is also exported for use in custom configurations:
90
+
91
+ ```typescript
92
+ import { shouldThrow } from '@rpckit/fallback/electrum-cash'
93
+ ```
94
+
95
+ ## Response Observation
96
+
97
+ Monitor all requests and responses across transports:
98
+
99
+ ```typescript
100
+ const unsub = transport.onResponse(({ method, params, transport, response, error, status }) => {
101
+ console.log(`${method} via ${transport.url}: ${status}`)
102
+ if (status === 'error') {
103
+ console.error('Failed:', error)
104
+ }
105
+ })
106
+ // Later: unsub()
107
+ ```
@@ -0,0 +1,8 @@
1
+ import type { FallbackTransport, FallbackTransportOptions } from '@rpckit/core';
2
+ /** Default shouldThrow for Electrum Cash / BCHN: throws for all deterministic
3
+ * RPC errors (invalid params, bad address, verify rejected, etc.) and falls
4
+ * through on transient server-health issues (internal error, OOM, warmup). */
5
+ export declare function shouldThrow(error: Error): boolean | undefined;
6
+ export declare function fallback<T>(transports: [T], options?: FallbackTransportOptions): T;
7
+ export declare function fallback<T>(transports: [T, T, ...T[]], options?: FallbackTransportOptions): FallbackTransport;
8
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../src/electrum-cash/fallback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,iBAAiB,EACjB,wBAAwB,EAIzB,MAAM,cAAc,CAAA;AAarB;;+EAE+E;AAC/E,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAQ7D;AAGD,wBAAgB,QAAQ,CAAC,CAAC,EACxB,UAAU,EAAE,CAAC,CAAC,CAAC,EACf,OAAO,CAAC,EAAE,wBAAwB,GACjC,CAAC,CAAA;AAGJ,wBAAgB,QAAQ,CAAC,CAAC,EACxB,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GACjC,iBAAiB,CAAA"}
@@ -0,0 +1,40 @@
1
+ import { fallback as baseFallback } from '../fallback.js';
2
+ /** Transient server-specific errors worth retrying on another server. */
3
+ const TRANSIENT_CODES = new Set([
4
+ -32603, // RPC_INTERNAL_ERROR — server corruption/bug
5
+ -7, // RPC_OUT_OF_MEMORY
6
+ -20, // RPC_DATABASE_ERROR
7
+ -28, // RPC_IN_WARMUP — server still starting
8
+ -9, // RPC_CLIENT_NOT_CONNECTED — server's node disconnected
9
+ -10, // RPC_CLIENT_IN_INITIAL_DOWNLOAD — server still syncing
10
+ ]);
11
+ /** Default shouldThrow for Electrum Cash / BCHN: throws for all deterministic
12
+ * RPC errors (invalid params, bad address, verify rejected, etc.) and falls
13
+ * through on transient server-health issues (internal error, OOM, warmup). */
14
+ export function shouldThrow(error) {
15
+ if ('code' in error &&
16
+ typeof error.code === 'number') {
17
+ return !TRANSIENT_CODES.has(error.code);
18
+ }
19
+ return false;
20
+ }
21
+ // Implementation
22
+ export function fallback(transports, options = {}) {
23
+ // biome-ignore lint/suspicious/noExplicitAny: overload forwarding requires type erasure
24
+ return baseFallback(transports, resolveOptions(options));
25
+ }
26
+ function resolveOptions(options) {
27
+ const resolved = { ...options };
28
+ if (!resolved.shouldThrow) {
29
+ resolved.shouldThrow = shouldThrow;
30
+ }
31
+ if (resolved.rank) {
32
+ const rankOpts = typeof resolved.rank === 'object' ? { ...resolved.rank } : {};
33
+ if (!rankOpts.ping) {
34
+ rankOpts.ping = (t) => t.request('server.ping');
35
+ }
36
+ resolved.rank = rankOpts;
37
+ }
38
+ return resolved;
39
+ }
40
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/electrum-cash/fallback.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAEzD,yEAAyE;AACzE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,CAAC,KAAK,EAAE,6CAA6C;IACrD,CAAC,CAAC,EAAE,oBAAoB;IACxB,CAAC,EAAE,EAAE,qBAAqB;IAC1B,CAAC,EAAE,EAAE,wCAAwC;IAC7C,CAAC,CAAC,EAAE,wDAAwD;IAC5D,CAAC,EAAE,EAAE,wDAAwD;CAC9D,CAAC,CAAA;AAEF;;+EAE+E;AAC/E,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,IACE,MAAM,IAAI,KAAK;QACf,OAAQ,KAA2B,CAAC,IAAI,KAAK,QAAQ,EACrD,CAAC;QACD,OAAO,CAAC,eAAe,CAAC,GAAG,CAAE,KAA0B,CAAC,IAAI,CAAC,CAAA;IAC/D,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAcD,iBAAiB;AACjB,MAAM,UAAU,QAAQ,CACtB,UAA0B,EAC1B,UAAuC,EAAE;IAEzC,wFAAwF;IACxF,OAAQ,YAAoB,CAAC,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;AACnE,CAAC;AAED,SAAS,cAAc,CACrB,OAAoC;IAEpC,MAAM,QAAQ,GAAgC,EAAE,GAAG,OAAO,EAAE,CAAA;IAE5D,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC1B,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAA;IACpC,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,QAAQ,GACZ,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAE/D,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAe,EAAE,EAAE,CAClC,CAAC,CAAC,OAAO,CAAC,aAAwC,CAAC,CAAA;QACvD,CAAC;QAED,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAA;IAC1B,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { fallback, shouldThrow } from './fallback.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/electrum-cash/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { fallback, shouldThrow } from './fallback.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/electrum-cash/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,6 @@
1
+ import type { FallbackTransport, FallbackTransportOptions } from '@rpckit/core';
2
+ export declare function fallback<T>(transports: [T], options?: FallbackTransportOptions): T;
3
+ export declare function fallback<T>(transports: [T, T, ...T[]], options?: FallbackTransportOptions): FallbackTransport;
4
+ /** Default shouldThrow: stops fallback for deterministic JSON-RPC errors. */
5
+ export declare function shouldThrow(error: Error): boolean | undefined;
6
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../src/fallback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,wBAAwB,EAMzB,MAAM,cAAc,CAAA;AAGrB,wBAAgB,QAAQ,CAAC,CAAC,EACxB,UAAU,EAAE,CAAC,CAAC,CAAC,EACf,OAAO,CAAC,EAAE,wBAAwB,GACjC,CAAC,CAAA;AAGJ,wBAAgB,QAAQ,CAAC,CAAC,EACxB,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GACjC,iBAAiB,CAAA;AA4OpB,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAc7D"}
@@ -0,0 +1,208 @@
1
+ // Implementation
2
+ export function fallback(transports, options = {}) {
3
+ // Single transport: no need to wrap
4
+ if (transports.length === 1) {
5
+ return transports[0];
6
+ }
7
+ let ranked = [...transports];
8
+ const { shouldThrow: shouldThrow_ = shouldThrow } = options;
9
+ let rankingTimer = null;
10
+ let rankingStopped = false;
11
+ let currentScores = transports.map((t) => ({
12
+ transport: t,
13
+ score: 0,
14
+ latency: 0,
15
+ stability: 0,
16
+ }));
17
+ const scoreListeners = new Set();
18
+ const responseListeners = new Set();
19
+ if (options.rank) {
20
+ const rankOpts = typeof options.rank === 'object' ? options.rank : {};
21
+ startRanking(transports, rankOpts);
22
+ }
23
+ function startRanking(transports, opts) {
24
+ if (!opts.ping)
25
+ return;
26
+ const ping = opts.ping;
27
+ const interval = opts.interval ?? 4000;
28
+ const sampleCount = opts.sampleCount ?? 10;
29
+ const timeout = opts.timeout ?? 1000;
30
+ const latencyWeight = opts.weights?.latency ?? 0.3;
31
+ const stabilityWeight = opts.weights?.stability ?? 0.7;
32
+ const samples = [];
33
+ async function sample() {
34
+ if (rankingStopped)
35
+ return;
36
+ const results = await Promise.all(transports.map(async (transport) => {
37
+ const start = performance.now();
38
+ try {
39
+ await Promise.race([
40
+ ping(transport),
41
+ new Promise((_, reject) => setTimeout(() => reject(new Error('ping timeout')), timeout)),
42
+ ]);
43
+ return { latency: performance.now() - start, success: 1 };
44
+ }
45
+ catch {
46
+ return { latency: timeout, success: 0 };
47
+ }
48
+ }));
49
+ samples.push(results);
50
+ if (samples.length > sampleCount)
51
+ samples.shift();
52
+ const maxLatency = Math.max(...samples.flatMap((s) => s.map((r) => r.latency)));
53
+ const scores = transports.map((transport, i) => {
54
+ const latencies = samples.map((s) => s[i].latency);
55
+ const meanLatency = latencies.reduce((a, b) => a + b, 0) / latencies.length;
56
+ const latencyScore = maxLatency > 0 ? 1 - meanLatency / maxLatency : 0;
57
+ const successes = samples.map((s) => s[i].success);
58
+ const stabilityScore = successes.reduce((a, b) => a + b, 0) / successes.length;
59
+ const score = stabilityScore === 0
60
+ ? 0
61
+ : latencyWeight * latencyScore + stabilityWeight * stabilityScore;
62
+ return {
63
+ transport,
64
+ score,
65
+ latency: meanLatency,
66
+ stability: stabilityScore,
67
+ };
68
+ });
69
+ scores.sort((a, b) => b.score - a.score);
70
+ ranked = scores.map((s) => s.transport);
71
+ currentScores = scores;
72
+ for (const listener of scoreListeners) {
73
+ listener(scores);
74
+ }
75
+ if (!rankingStopped) {
76
+ rankingTimer = setTimeout(sample, interval);
77
+ }
78
+ }
79
+ sample();
80
+ }
81
+ return {
82
+ url: transports.map((t) => t.url).join(','),
83
+ async connect() {
84
+ if (options.eagerConnect) {
85
+ const connectResults = ranked.map((t, i) => t.connect().then(() => i));
86
+ const fastestIndex = await Promise.any(connectResults);
87
+ // Move the fastest-connecting transport to front priority
88
+ if (fastestIndex > 0) {
89
+ const [fastest] = ranked.splice(fastestIndex, 1);
90
+ ranked.unshift(fastest);
91
+ }
92
+ // Let remaining connections settle in background
93
+ Promise.allSettled(connectResults);
94
+ }
95
+ else {
96
+ await Promise.all(ranked.map((t) => t.connect()));
97
+ }
98
+ },
99
+ get transports() {
100
+ return ranked;
101
+ },
102
+ get scores() {
103
+ return currentScores;
104
+ },
105
+ onScores(listener) {
106
+ scoreListeners.add(listener);
107
+ return () => {
108
+ scoreListeners.delete(listener);
109
+ };
110
+ },
111
+ onResponse(listener) {
112
+ responseListeners.add(listener);
113
+ return () => {
114
+ responseListeners.delete(listener);
115
+ };
116
+ },
117
+ async request(method, ...params) {
118
+ let lastError;
119
+ for (const transport of ranked) {
120
+ try {
121
+ // biome-ignore lint/suspicious/noExplicitAny: meta-transport delegates with erased types
122
+ const response = await transport.request(method, ...params);
123
+ for (const listener of responseListeners) {
124
+ listener({
125
+ method,
126
+ params,
127
+ transport,
128
+ response,
129
+ status: 'success',
130
+ });
131
+ }
132
+ return response;
133
+ }
134
+ catch (error) {
135
+ lastError = error;
136
+ for (const listener of responseListeners) {
137
+ listener({
138
+ method,
139
+ params,
140
+ transport,
141
+ error,
142
+ status: 'error',
143
+ });
144
+ }
145
+ if (shouldThrow_(error))
146
+ throw error;
147
+ }
148
+ }
149
+ throw lastError;
150
+ },
151
+ async subscribe(method, ...args) {
152
+ const onData = args.pop();
153
+ const params = args;
154
+ let lastError;
155
+ for (const transport of ranked) {
156
+ try {
157
+ // biome-ignore lint/suspicious/noExplicitAny: meta-transport delegates with erased types
158
+ const result = await transport.subscribe(method, ...params, onData);
159
+ for (const listener of responseListeners) {
160
+ listener({
161
+ method,
162
+ params,
163
+ transport,
164
+ response: result,
165
+ status: 'success',
166
+ });
167
+ }
168
+ return result;
169
+ }
170
+ catch (error) {
171
+ lastError = error;
172
+ for (const listener of responseListeners) {
173
+ listener({
174
+ method,
175
+ params,
176
+ transport,
177
+ error,
178
+ status: 'error',
179
+ });
180
+ }
181
+ }
182
+ }
183
+ throw lastError;
184
+ },
185
+ async close() {
186
+ rankingStopped = true;
187
+ if (rankingTimer)
188
+ clearTimeout(rankingTimer);
189
+ scoreListeners.clear();
190
+ responseListeners.clear();
191
+ await Promise.all(transports.map((t) => t.close()));
192
+ },
193
+ };
194
+ }
195
+ /** Default shouldThrow: stops fallback for deterministic JSON-RPC errors. */
196
+ export function shouldThrow(error) {
197
+ if ('code' in error &&
198
+ typeof error.code === 'number') {
199
+ const code = error.code;
200
+ if (code === -32700 || // Parse error
201
+ code === -32600 || // Invalid Request
202
+ code === -32602 // Invalid params
203
+ )
204
+ return true;
205
+ }
206
+ return false;
207
+ }
208
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../src/fallback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { fallback, shouldThrow } from './fallback.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { fallback, shouldThrow } from './fallback.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@rpckit/fallback",
3
+ "version": "0.9.99",
4
+ "description": "Fallback meta-transport for rpckit with automatic failover and health ranking",
5
+ "author": "mainnet_pat",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./electrum-cash": {
17
+ "types": "./dist/electrum-cash/index.d.ts",
18
+ "default": "./dist/electrum-cash/index.js"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "keywords": [
25
+ "json-rpc",
26
+ "rpc",
27
+ "fallback",
28
+ "failover",
29
+ "typescript"
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/mainnet-pat/rpckit.git",
34
+ "directory": "packages/fallback"
35
+ },
36
+ "homepage": "https://rpckit.dev",
37
+ "bugs": {
38
+ "url": "https://github.com/mainnet-pat/rpckit/issues"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc"
42
+ },
43
+ "dependencies": {
44
+ "@rpckit/core": "*"
45
+ },
46
+ "devDependencies": {
47
+ "typescript": "^5.7.0"
48
+ }
49
+ }