ton-provider-system 0.1.8 → 0.1.10
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/index.cjs +88 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +88 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1082,6 +1082,7 @@ declare class ProviderSelector {
|
|
|
1082
1082
|
private autoSelect;
|
|
1083
1083
|
private customEndpoint;
|
|
1084
1084
|
private bestProviderByNetwork;
|
|
1085
|
+
private activeProviderByNetwork;
|
|
1085
1086
|
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger);
|
|
1086
1087
|
/**
|
|
1087
1088
|
* Get the best provider for a network
|
|
@@ -1137,8 +1138,9 @@ declare class ProviderSelector {
|
|
|
1137
1138
|
isUsingCustomEndpoint(): boolean;
|
|
1138
1139
|
/**
|
|
1139
1140
|
* Clear cached best providers (forces recalculation)
|
|
1141
|
+
* @param network - Optional network to clear cache for. If not provided, clears all networks.
|
|
1140
1142
|
*/
|
|
1141
|
-
clearCache(): void;
|
|
1143
|
+
clearCache(network?: Network): void;
|
|
1142
1144
|
/**
|
|
1143
1145
|
* Update best provider after health check
|
|
1144
1146
|
*/
|
|
@@ -1147,6 +1149,11 @@ declare class ProviderSelector {
|
|
|
1147
1149
|
* Handle provider failure (switch to next best)
|
|
1148
1150
|
*/
|
|
1149
1151
|
handleProviderFailure(providerId: string, network: Network): ResolvedProvider | null;
|
|
1152
|
+
/**
|
|
1153
|
+
* Get the currently active provider ID for a network
|
|
1154
|
+
* (the one that was last selected and is being used)
|
|
1155
|
+
*/
|
|
1156
|
+
getActiveProviderId(network: Network): string | null;
|
|
1150
1157
|
/**
|
|
1151
1158
|
* Get active provider info
|
|
1152
1159
|
*/
|
|
@@ -1248,8 +1255,10 @@ declare class ProviderManager {
|
|
|
1248
1255
|
* Get endpoint with rate limiting
|
|
1249
1256
|
*
|
|
1250
1257
|
* Waits for rate limit token before returning endpoint.
|
|
1258
|
+
*
|
|
1259
|
+
* @param forceRefresh - If true, clears cache and forces re-selection
|
|
1251
1260
|
*/
|
|
1252
|
-
getEndpointWithRateLimit(timeoutMs?: number): Promise<string>;
|
|
1261
|
+
getEndpointWithRateLimit(timeoutMs?: number, forceRefresh?: boolean): Promise<string>;
|
|
1253
1262
|
/**
|
|
1254
1263
|
* Get current active provider
|
|
1255
1264
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1082,6 +1082,7 @@ declare class ProviderSelector {
|
|
|
1082
1082
|
private autoSelect;
|
|
1083
1083
|
private customEndpoint;
|
|
1084
1084
|
private bestProviderByNetwork;
|
|
1085
|
+
private activeProviderByNetwork;
|
|
1085
1086
|
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger);
|
|
1086
1087
|
/**
|
|
1087
1088
|
* Get the best provider for a network
|
|
@@ -1137,8 +1138,9 @@ declare class ProviderSelector {
|
|
|
1137
1138
|
isUsingCustomEndpoint(): boolean;
|
|
1138
1139
|
/**
|
|
1139
1140
|
* Clear cached best providers (forces recalculation)
|
|
1141
|
+
* @param network - Optional network to clear cache for. If not provided, clears all networks.
|
|
1140
1142
|
*/
|
|
1141
|
-
clearCache(): void;
|
|
1143
|
+
clearCache(network?: Network): void;
|
|
1142
1144
|
/**
|
|
1143
1145
|
* Update best provider after health check
|
|
1144
1146
|
*/
|
|
@@ -1147,6 +1149,11 @@ declare class ProviderSelector {
|
|
|
1147
1149
|
* Handle provider failure (switch to next best)
|
|
1148
1150
|
*/
|
|
1149
1151
|
handleProviderFailure(providerId: string, network: Network): ResolvedProvider | null;
|
|
1152
|
+
/**
|
|
1153
|
+
* Get the currently active provider ID for a network
|
|
1154
|
+
* (the one that was last selected and is being used)
|
|
1155
|
+
*/
|
|
1156
|
+
getActiveProviderId(network: Network): string | null;
|
|
1150
1157
|
/**
|
|
1151
1158
|
* Get active provider info
|
|
1152
1159
|
*/
|
|
@@ -1248,8 +1255,10 @@ declare class ProviderManager {
|
|
|
1248
1255
|
* Get endpoint with rate limiting
|
|
1249
1256
|
*
|
|
1250
1257
|
* Waits for rate limit token before returning endpoint.
|
|
1258
|
+
*
|
|
1259
|
+
* @param forceRefresh - If true, clears cache and forces re-selection
|
|
1251
1260
|
*/
|
|
1252
|
-
getEndpointWithRateLimit(timeoutMs?: number): Promise<string>;
|
|
1261
|
+
getEndpointWithRateLimit(timeoutMs?: number, forceRefresh?: boolean): Promise<string>;
|
|
1253
1262
|
/**
|
|
1254
1263
|
* Get current active provider
|
|
1255
1264
|
*/
|
package/dist/index.js
CHANGED
|
@@ -949,13 +949,16 @@ var HealthChecker = class {
|
|
|
949
949
|
const existing = this.results.get(key);
|
|
950
950
|
const result = existing ? {
|
|
951
951
|
...existing,
|
|
952
|
+
success: true,
|
|
953
|
+
// Degraded providers are still usable, just slower/rate-limited
|
|
952
954
|
status: "degraded",
|
|
953
955
|
error: error || "Marked as degraded",
|
|
954
956
|
lastTested: /* @__PURE__ */ new Date()
|
|
955
957
|
} : {
|
|
956
958
|
id: providerId,
|
|
957
959
|
network,
|
|
958
|
-
success:
|
|
960
|
+
success: true,
|
|
961
|
+
// Degraded providers are still usable
|
|
959
962
|
status: "degraded",
|
|
960
963
|
latencyMs: null,
|
|
961
964
|
seqno: null,
|
|
@@ -1569,6 +1572,8 @@ var ProviderSelector = class {
|
|
|
1569
1572
|
this.autoSelect = true;
|
|
1570
1573
|
this.customEndpoint = null;
|
|
1571
1574
|
this.bestProviderByNetwork = /* @__PURE__ */ new Map();
|
|
1575
|
+
// Track currently active provider per network (the one actually being used)
|
|
1576
|
+
this.activeProviderByNetwork = /* @__PURE__ */ new Map();
|
|
1572
1577
|
this.registry = registry;
|
|
1573
1578
|
this.healthChecker = healthChecker;
|
|
1574
1579
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
@@ -1587,6 +1592,7 @@ var ProviderSelector = class {
|
|
|
1587
1592
|
if (!this.autoSelect && this.selectedProviderId) {
|
|
1588
1593
|
const provider = this.registry.getProvider(this.selectedProviderId);
|
|
1589
1594
|
if (provider && provider.network === network) {
|
|
1595
|
+
this.activeProviderByNetwork.set(network, provider.id);
|
|
1590
1596
|
return provider;
|
|
1591
1597
|
}
|
|
1592
1598
|
this.logger.warn(
|
|
@@ -1597,8 +1603,13 @@ var ProviderSelector = class {
|
|
|
1597
1603
|
if (cachedBestId) {
|
|
1598
1604
|
const cached = this.registry.getProvider(cachedBestId);
|
|
1599
1605
|
const health = this.healthChecker.getResult(cachedBestId, network);
|
|
1600
|
-
if (cached && health && health.success !== false &&
|
|
1606
|
+
if (cached && health && health.success !== false && health.success !== void 0 && // Explicitly check for undefined
|
|
1607
|
+
this.config.minStatus.includes(health.status)) {
|
|
1608
|
+
this.activeProviderByNetwork.set(network, cachedBestId);
|
|
1601
1609
|
return cached;
|
|
1610
|
+
} else {
|
|
1611
|
+
this.bestProviderByNetwork.delete(network);
|
|
1612
|
+
this.activeProviderByNetwork.delete(network);
|
|
1602
1613
|
}
|
|
1603
1614
|
}
|
|
1604
1615
|
return this.findBestProvider(network);
|
|
@@ -1620,12 +1631,31 @@ var ProviderSelector = class {
|
|
|
1620
1631
|
const defaults = this.registry.getDefaultOrderForNetwork(network);
|
|
1621
1632
|
for (const defaultProvider of defaults) {
|
|
1622
1633
|
const health = this.healthChecker.getResult(defaultProvider.id, network);
|
|
1623
|
-
if (!health || health.status === "untested"
|
|
1634
|
+
if (!health || health.status === "untested") {
|
|
1635
|
+
this.logger.warn(
|
|
1636
|
+
`No healthy providers for ${network}, using untested default: ${defaultProvider.id}`
|
|
1637
|
+
);
|
|
1638
|
+
this.activeProviderByNetwork.set(network, defaultProvider.id);
|
|
1639
|
+
return defaultProvider;
|
|
1640
|
+
}
|
|
1641
|
+
if (health.success === true) {
|
|
1624
1642
|
this.logger.warn(
|
|
1625
1643
|
`No healthy providers for ${network}, using default: ${defaultProvider.id}`
|
|
1626
1644
|
);
|
|
1645
|
+
this.activeProviderByNetwork.set(network, defaultProvider.id);
|
|
1627
1646
|
return defaultProvider;
|
|
1628
1647
|
}
|
|
1648
|
+
if (health.success === false && health.lastTested) {
|
|
1649
|
+
const timeSinceFailure = Date.now() - health.lastTested.getTime();
|
|
1650
|
+
const cooldownMs = 3e4;
|
|
1651
|
+
if (timeSinceFailure > cooldownMs) {
|
|
1652
|
+
this.logger.warn(
|
|
1653
|
+
`No healthy providers for ${network}, retrying failed default after cooldown: ${defaultProvider.id}`
|
|
1654
|
+
);
|
|
1655
|
+
this.activeProviderByNetwork.set(network, defaultProvider.id);
|
|
1656
|
+
return defaultProvider;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1629
1659
|
}
|
|
1630
1660
|
for (const provider of providers) {
|
|
1631
1661
|
const health = this.healthChecker.getResult(provider.id, network);
|
|
@@ -1633,20 +1663,34 @@ var ProviderSelector = class {
|
|
|
1633
1663
|
this.logger.warn(
|
|
1634
1664
|
`No tested healthy providers for ${network}, using untested: ${provider.id}`
|
|
1635
1665
|
);
|
|
1666
|
+
this.activeProviderByNetwork.set(network, provider.id);
|
|
1636
1667
|
return provider;
|
|
1637
1668
|
}
|
|
1669
|
+
if (health.success === false && health.lastTested) {
|
|
1670
|
+
const timeSinceFailure = Date.now() - health.lastTested.getTime();
|
|
1671
|
+
const cooldownMs = 3e4;
|
|
1672
|
+
if (timeSinceFailure > cooldownMs) {
|
|
1673
|
+
this.logger.warn(
|
|
1674
|
+
`No healthy providers for ${network}, retrying failed provider after cooldown: ${provider.id}`
|
|
1675
|
+
);
|
|
1676
|
+
this.activeProviderByNetwork.set(network, provider.id);
|
|
1677
|
+
return provider;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1638
1680
|
}
|
|
1639
|
-
this.logger.error(`No available providers for ${network} (all tested and failed)`);
|
|
1681
|
+
this.logger.error(`No available providers for ${network} (all tested and failed, cooldown active)`);
|
|
1640
1682
|
return null;
|
|
1641
1683
|
}
|
|
1642
1684
|
const best = scored[0].provider;
|
|
1643
1685
|
const bestHealth = this.healthChecker.getResult(best.id, network);
|
|
1644
1686
|
if (bestHealth && bestHealth.success === true) {
|
|
1645
1687
|
this.bestProviderByNetwork.set(network, best.id);
|
|
1688
|
+
this.activeProviderByNetwork.set(network, best.id);
|
|
1646
1689
|
this.logger.debug(
|
|
1647
1690
|
`Best provider for ${network}: ${best.id} (score: ${scored[0].score.toFixed(2)})`
|
|
1648
1691
|
);
|
|
1649
1692
|
} else {
|
|
1693
|
+
this.activeProviderByNetwork.set(network, best.id);
|
|
1650
1694
|
this.logger.debug(
|
|
1651
1695
|
`Best provider for ${network}: ${best.id} (score: ${scored[0].score.toFixed(2)}, untested)`
|
|
1652
1696
|
);
|
|
@@ -1689,6 +1733,13 @@ var ProviderSelector = class {
|
|
|
1689
1733
|
return 0.01 * (1 / (provider.priority + 1));
|
|
1690
1734
|
}
|
|
1691
1735
|
if (health.success === false) {
|
|
1736
|
+
if (health.lastTested) {
|
|
1737
|
+
const timeSinceFailure = Date.now() - health.lastTested.getTime();
|
|
1738
|
+
const cooldownMs = 3e4;
|
|
1739
|
+
if (timeSinceFailure > cooldownMs) {
|
|
1740
|
+
return 1e-3 * (1 / (provider.priority + 1));
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1692
1743
|
return 0;
|
|
1693
1744
|
}
|
|
1694
1745
|
if (health.status === "offline") {
|
|
@@ -1786,9 +1837,16 @@ var ProviderSelector = class {
|
|
|
1786
1837
|
}
|
|
1787
1838
|
/**
|
|
1788
1839
|
* Clear cached best providers (forces recalculation)
|
|
1840
|
+
* @param network - Optional network to clear cache for. If not provided, clears all networks.
|
|
1789
1841
|
*/
|
|
1790
|
-
clearCache() {
|
|
1791
|
-
|
|
1842
|
+
clearCache(network) {
|
|
1843
|
+
if (network) {
|
|
1844
|
+
this.bestProviderByNetwork.delete(network);
|
|
1845
|
+
this.activeProviderByNetwork.delete(network);
|
|
1846
|
+
} else {
|
|
1847
|
+
this.bestProviderByNetwork.clear();
|
|
1848
|
+
this.activeProviderByNetwork.clear();
|
|
1849
|
+
}
|
|
1792
1850
|
}
|
|
1793
1851
|
/**
|
|
1794
1852
|
* Update best provider after health check
|
|
@@ -1803,8 +1861,16 @@ var ProviderSelector = class {
|
|
|
1803
1861
|
if (this.bestProviderByNetwork.get(network) === providerId) {
|
|
1804
1862
|
this.bestProviderByNetwork.delete(network);
|
|
1805
1863
|
}
|
|
1864
|
+
this.activeProviderByNetwork.delete(network);
|
|
1806
1865
|
return this.getNextProvider(network, [providerId]);
|
|
1807
1866
|
}
|
|
1867
|
+
/**
|
|
1868
|
+
* Get the currently active provider ID for a network
|
|
1869
|
+
* (the one that was last selected and is being used)
|
|
1870
|
+
*/
|
|
1871
|
+
getActiveProviderId(network) {
|
|
1872
|
+
return this.activeProviderByNetwork.get(network) || null;
|
|
1873
|
+
}
|
|
1808
1874
|
// ========================================================================
|
|
1809
1875
|
// Info
|
|
1810
1876
|
// ========================================================================
|
|
@@ -2041,6 +2107,7 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2041
2107
|
this.options.logger.warn("No providers available, using fallback");
|
|
2042
2108
|
return this.getFallbackEndpoint();
|
|
2043
2109
|
}
|
|
2110
|
+
this.selector.getActiveProviderId(this.network) || this.selector.getBestProvider(this.network);
|
|
2044
2111
|
if (provider.isDynamic && provider.type === "orbs") {
|
|
2045
2112
|
try {
|
|
2046
2113
|
const { getHttpEndpoint } = await import('@orbs-network/ton-access');
|
|
@@ -2056,9 +2123,14 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2056
2123
|
* Get endpoint with rate limiting
|
|
2057
2124
|
*
|
|
2058
2125
|
* Waits for rate limit token before returning endpoint.
|
|
2126
|
+
*
|
|
2127
|
+
* @param forceRefresh - If true, clears cache and forces re-selection
|
|
2059
2128
|
*/
|
|
2060
|
-
async getEndpointWithRateLimit(timeoutMs) {
|
|
2129
|
+
async getEndpointWithRateLimit(timeoutMs, forceRefresh = false) {
|
|
2061
2130
|
this.ensureInitialized();
|
|
2131
|
+
if (forceRefresh) {
|
|
2132
|
+
this.selector.clearCache(this.network);
|
|
2133
|
+
}
|
|
2062
2134
|
const provider = this.selector.getBestProvider(this.network);
|
|
2063
2135
|
if (!provider) {
|
|
2064
2136
|
return this.getFallbackEndpoint();
|
|
@@ -2110,7 +2182,14 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2110
2182
|
*/
|
|
2111
2183
|
reportError(error) {
|
|
2112
2184
|
if (!this.initialized || !this.network) return;
|
|
2113
|
-
const
|
|
2185
|
+
const activeProviderId = this.selector.getActiveProviderId(this.network);
|
|
2186
|
+
let provider = null;
|
|
2187
|
+
if (activeProviderId) {
|
|
2188
|
+
provider = this.registry.getProvider(activeProviderId) || null;
|
|
2189
|
+
}
|
|
2190
|
+
if (!provider) {
|
|
2191
|
+
provider = this.selector.getBestProvider(this.network);
|
|
2192
|
+
}
|
|
2114
2193
|
if (!provider) return;
|
|
2115
2194
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2116
2195
|
const errorMsgLower = errorMsg.toLowerCase();
|
|
@@ -2129,6 +2208,7 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2129
2208
|
this.rateLimiter.reportError(provider.id);
|
|
2130
2209
|
this.healthChecker.markDegraded(provider.id, this.network, errorMsg);
|
|
2131
2210
|
}
|
|
2211
|
+
this.selector.clearCache(this.network);
|
|
2132
2212
|
this.selector.handleProviderFailure(provider.id, this.network);
|
|
2133
2213
|
this.notifyListeners();
|
|
2134
2214
|
}
|