@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 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
- * Fetch API wrapper that retries until timeout is reached.
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';