@hiveio/dhive 1.3.2 → 1.3.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/dist/dhive.d.ts +142 -2
- package/dist/dhive.js +27 -18
- package/dist/dhive.js.gz +0 -0
- package/dist/dhive.js.map +1 -1
- package/lib/client.d.ts +11 -0
- package/lib/client.js +33 -4
- package/lib/health-tracker.d.ts +100 -0
- package/lib/health-tracker.js +167 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/utils.d.ts +26 -2
- package/lib/utils.js +150 -43
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/dist/dhive.d.ts
CHANGED
|
@@ -2,6 +2,109 @@ declare module 'dhive/version' {
|
|
|
2
2
|
const _default: string;
|
|
3
3
|
export default _default;
|
|
4
4
|
|
|
5
|
+
}
|
|
6
|
+
declare module 'dhive/health-tracker' {
|
|
7
|
+
/**
|
|
8
|
+
* @file Node health tracking for smart failover.
|
|
9
|
+
* @license BSD-3-Clause-No-Military-License
|
|
10
|
+
*
|
|
11
|
+
* Tracks per-node, per-API health to enable intelligent failover decisions.
|
|
12
|
+
* Nodes that fail for specific APIs are deprioritized for those APIs while
|
|
13
|
+
* remaining available for others. Stale nodes (behind on head block) are
|
|
14
|
+
* also deprioritized.
|
|
15
|
+
*/
|
|
16
|
+
export interface HealthTrackerOptions {
|
|
17
|
+
/**
|
|
18
|
+
* How long (ms) to deprioritize a node after consecutive failures.
|
|
19
|
+
* Default: 30 seconds.
|
|
20
|
+
*/
|
|
21
|
+
nodeCooldownMs?: number;
|
|
22
|
+
/**
|
|
23
|
+
* How long (ms) to deprioritize a node for a specific API after failures.
|
|
24
|
+
* Default: 60 seconds.
|
|
25
|
+
*/
|
|
26
|
+
apiCooldownMs?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Number of consecutive failures before a node enters cooldown.
|
|
29
|
+
* Default: 3.
|
|
30
|
+
*/
|
|
31
|
+
maxFailuresBeforeCooldown?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Number of API-specific failures before deprioritizing for that API.
|
|
34
|
+
* Default: 2.
|
|
35
|
+
*/
|
|
36
|
+
maxApiFailuresBeforeCooldown?: number;
|
|
37
|
+
/**
|
|
38
|
+
* How many blocks behind the best known head block a node can be
|
|
39
|
+
* before being considered stale. Default: 30.
|
|
40
|
+
*/
|
|
41
|
+
staleBlockThreshold?: number;
|
|
42
|
+
/**
|
|
43
|
+
* How long (ms) head block data remains valid for staleness checks.
|
|
44
|
+
* Default: 2 minutes.
|
|
45
|
+
*/
|
|
46
|
+
headBlockTtlMs?: number;
|
|
47
|
+
}
|
|
48
|
+
export class NodeHealthTracker {
|
|
49
|
+
private health;
|
|
50
|
+
private bestKnownHeadBlock;
|
|
51
|
+
private bestKnownHeadBlockTime;
|
|
52
|
+
private readonly nodeCooldownMs;
|
|
53
|
+
private readonly apiCooldownMs;
|
|
54
|
+
private readonly maxFailuresBeforeCooldown;
|
|
55
|
+
private readonly maxApiFailuresBeforeCooldown;
|
|
56
|
+
private readonly staleBlockThreshold;
|
|
57
|
+
private readonly headBlockTtlMs;
|
|
58
|
+
constructor(options?: HealthTrackerOptions);
|
|
59
|
+
private getOrCreate;
|
|
60
|
+
/**
|
|
61
|
+
* Record a successful call to a node for a specific API.
|
|
62
|
+
* Clears consecutive failure counter and API-specific failures for this API.
|
|
63
|
+
*/
|
|
64
|
+
recordSuccess(node: string, api: string): void;
|
|
65
|
+
/**
|
|
66
|
+
* Record a network-level failure (timeout, connection refused, HTTP error).
|
|
67
|
+
* Increments both the global consecutive failure counter and the API-specific counter.
|
|
68
|
+
*/
|
|
69
|
+
recordFailure(node: string, api: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Record an API/plugin-specific failure (e.g. "method not found", "plugin not enabled").
|
|
72
|
+
* Only increments the per-API counter, NOT the global consecutive failure counter.
|
|
73
|
+
* This prevents a node with a disabled plugin from being penalized for all APIs.
|
|
74
|
+
*/
|
|
75
|
+
recordApiFailure(node: string, api: string): void;
|
|
76
|
+
private incrementApiFailure;
|
|
77
|
+
/**
|
|
78
|
+
* Update head block number for a node.
|
|
79
|
+
* Called passively when get_dynamic_global_properties responses are observed.
|
|
80
|
+
*/
|
|
81
|
+
updateHeadBlock(node: string, headBlock: number): void;
|
|
82
|
+
/**
|
|
83
|
+
* Check if a node is considered healthy for a given API.
|
|
84
|
+
*/
|
|
85
|
+
isNodeHealthy(node: string, api?: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Return nodes ordered by health for a specific API call.
|
|
88
|
+
* Healthy nodes come first (preserving original order), then unhealthy nodes as fallback.
|
|
89
|
+
*/
|
|
90
|
+
getOrderedNodes(allNodes: string[], api?: string): string[];
|
|
91
|
+
/**
|
|
92
|
+
* Reset all health tracking data.
|
|
93
|
+
*/
|
|
94
|
+
reset(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Get a snapshot of current health state for diagnostics.
|
|
97
|
+
*/
|
|
98
|
+
getHealthSnapshot(): Map<string, {
|
|
99
|
+
consecutiveFailures: number;
|
|
100
|
+
headBlock: number;
|
|
101
|
+
apiFailures: Record<string, {
|
|
102
|
+
count: number;
|
|
103
|
+
}>;
|
|
104
|
+
healthy: boolean;
|
|
105
|
+
}>;
|
|
106
|
+
}
|
|
107
|
+
|
|
5
108
|
}
|
|
6
109
|
declare module 'dhive/chain/asset' {
|
|
7
110
|
/**
|
|
@@ -1872,6 +1975,20 @@ declare module 'dhive/utils' {
|
|
|
1872
1975
|
*/
|
|
1873
1976
|
/// <reference types="node" />
|
|
1874
1977
|
import { EventEmitter } from 'events';
|
|
1978
|
+
import { NodeHealthTracker } from 'dhive/health-tracker';
|
|
1979
|
+
/**
|
|
1980
|
+
* Context for smart retry/failover decisions.
|
|
1981
|
+
*/
|
|
1982
|
+
export interface RetryContext {
|
|
1983
|
+
/** Health tracker instance for per-node, per-API tracking */
|
|
1984
|
+
healthTracker?: NodeHealthTracker;
|
|
1985
|
+
/** The API being called (e.g. "bridge", "condenser_api", "database_api") */
|
|
1986
|
+
api?: string;
|
|
1987
|
+
/** Whether this is a broadcast operation — never retry after request may have been received */
|
|
1988
|
+
isBroadcast?: boolean;
|
|
1989
|
+
/** Whether to log failover events to console */
|
|
1990
|
+
consoleOnFailover?: boolean;
|
|
1991
|
+
}
|
|
1875
1992
|
/**
|
|
1876
1993
|
* Return a promise that will resove when a specific event is emitted.
|
|
1877
1994
|
*/
|
|
@@ -1889,9 +2006,19 @@ declare module 'dhive/utils' {
|
|
|
1889
2006
|
*/
|
|
1890
2007
|
export function copy<T>(object: T): T;
|
|
1891
2008
|
/**
|
|
1892
|
-
*
|
|
2009
|
+
* Smart fetch with immediate failover and per-node health tracking.
|
|
2010
|
+
*
|
|
2011
|
+
* For read operations:
|
|
2012
|
+
* - On failure, immediately try the next healthy node (no backoff within a round)
|
|
2013
|
+
* - After trying all nodes once (one round), apply backoff before the next round
|
|
2014
|
+
* - Stop after failoverThreshold rounds
|
|
2015
|
+
*
|
|
2016
|
+
* For broadcast operations:
|
|
2017
|
+
* - Only retry on pre-connection errors (ECONNREFUSED, ENOTFOUND, etc.)
|
|
2018
|
+
* where we know the request never reached the server
|
|
2019
|
+
* - NEVER retry after timeout or response errors to prevent double-broadcasting
|
|
1893
2020
|
*/
|
|
1894
|
-
export function retryingFetch(currentAddress: string, allAddresses: string | string[], opts: any, timeout: number, failoverThreshold: number, consoleOnFailover: boolean, backoff: (tries: number) => number, fetchTimeout?: (tries: number) => number): Promise<{
|
|
2021
|
+
export function retryingFetch(currentAddress: string, allAddresses: string | string[], opts: any, timeout: number, failoverThreshold: number, consoleOnFailover: boolean, backoff: (tries: number) => number, fetchTimeout?: (tries: number) => number, retryContext?: RetryContext): Promise<{
|
|
1895
2022
|
response: any;
|
|
1896
2023
|
currentAddress: string;
|
|
1897
2024
|
}>;
|
|
@@ -2796,6 +2923,7 @@ declare module 'dhive/client' {
|
|
|
2796
2923
|
import { AccountByKeyAPI } from 'dhive/helpers/key';
|
|
2797
2924
|
import { RCAPI } from 'dhive/helpers/rc';
|
|
2798
2925
|
import { TransactionStatusAPI } from 'dhive/helpers/transaction';
|
|
2926
|
+
import { NodeHealthTracker, HealthTrackerOptions } from 'dhive/health-tracker';
|
|
2799
2927
|
/**
|
|
2800
2928
|
* Library version.
|
|
2801
2929
|
*/
|
|
@@ -2858,6 +2986,11 @@ declare module 'dhive/client' {
|
|
|
2858
2986
|
* Deprecated - don't use
|
|
2859
2987
|
*/
|
|
2860
2988
|
rebrandedApi?: boolean;
|
|
2989
|
+
/**
|
|
2990
|
+
* Options for the node health tracker.
|
|
2991
|
+
* Controls cooldown periods, stale block thresholds, etc.
|
|
2992
|
+
*/
|
|
2993
|
+
healthTrackerOptions?: HealthTrackerOptions;
|
|
2861
2994
|
}
|
|
2862
2995
|
/**
|
|
2863
2996
|
* RPC Client
|
|
@@ -2902,6 +3035,11 @@ declare module 'dhive/client' {
|
|
|
2902
3035
|
* Transaction status API helper.
|
|
2903
3036
|
*/
|
|
2904
3037
|
readonly transaction: TransactionStatusAPI;
|
|
3038
|
+
/**
|
|
3039
|
+
* Node health tracker for smart failover.
|
|
3040
|
+
* Tracks per-node, per-API health and head block freshness.
|
|
3041
|
+
*/
|
|
3042
|
+
readonly healthTracker: NodeHealthTracker;
|
|
2905
3043
|
/**
|
|
2906
3044
|
* Chain ID for current network.
|
|
2907
3045
|
*/
|
|
@@ -3010,6 +3148,8 @@ declare module 'dhive' {
|
|
|
3010
3148
|
*/
|
|
3011
3149
|
import * as utils from 'dhive/utils';
|
|
3012
3150
|
export { utils };
|
|
3151
|
+
export { NodeHealthTracker } from 'dhive/health-tracker';
|
|
3152
|
+
export type { HealthTrackerOptions } from 'dhive/health-tracker';
|
|
3013
3153
|
export * from 'dhive/helpers/blockchain';
|
|
3014
3154
|
export * from 'dhive/helpers/database';
|
|
3015
3155
|
export * from 'dhive/helpers/rc';
|