Fallback meta-transport for rpckit with automatic failover and health ranking
npm install @rpckit/fallbackFallback meta-transport for rpckit. Provides automatic failover across multiple transports with optional health-based ranking.
``bash`
npm install @rpckit/core @rpckit/fallback
`typescript
import { fallback } from '@rpckit/fallback'
import { webSocket } from '@rpckit/websocket'
import { http } from '@rpckit/http'
const transport = fallback([
webSocket('wss://primary.example.com'),
http('https://backup.example.com'),
])
await transport.connect()
// Automatically tries next transport on failure
const result = await transport.request('my.method', 'param')
await transport.close()
`
- 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.rank
- - true or { interval, sampleCount, timeout, weights, ping } for health rankingeagerConnect
- - Connect to all transports in parallel (fastest transport is prioritized)
When rank is enabled, transports are periodically pinged and ranked by latency and stability. Requests are routed to the best-performing transport first.
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.
`typescript`
const transport = fallback(transports, {
rank: {
interval: 4000, // ms between health checks (default: 4000)
timeout: 1000, // ping timeout in ms (default: 1000)
sampleCount: 10, // number of samples to average (default: 10)
weights: {
latency: 0.3, // weight for latency score (default: 0.3)
stability: 0.7, // weight for stability score (default: 0.7)
},
ping: (t) => t.request('health.check'), // provide a ping function for your protocol
},
})
`typescript
// Get current scores
console.log(transport.scores)
// [{ transport, score, latency, stability }, ...]
// Get ranked transport list
console.log(transport.transports)
// Subscribe to score updates
const unsub = transport.onScores((scores) => {
console.log('Scores updated:', scores)
})
// Later: unsub()
`
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.):
`typescript
import { fallback } from '@rpckit/fallback/electrum-cash'
import { webSocket } from '@rpckit/websocket/electrum-cash'
const transport = fallback([
webSocket('wss://server1.example.com:50004'),
webSocket('wss://server2.example.com:50004'),
], { rank: true }) // Uses server.ping for health checks
`
The shouldThrow function is also exported for use in custom configurations:
`typescript`
import { shouldThrow } from '@rpckit/fallback/electrum-cash'
Monitor all requests and responses across transports:
`typescript${method} via ${transport.url}: ${status}
const unsub = transport.onResponse(({ method, params, transport, response, error, status }) => {
console.log()``
if (status === 'error') {
console.error('Failed:', error)
}
})
// Later: unsub()