@splashcodex/api-key-manager 1.0.0 → 3.0.0
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 +185 -39
- package/dist/index.d.ts +120 -29
- package/dist/index.js +348 -97
- package/dist/index.js.map +1 -1
- package/package.json +14 -5
- package/src/index.ts +453 -112
package/README.md
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
# @splashcodex/api-key-manager
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Universal API Key Rotation System with Resilience, Load Balancing & AI Gateway Features
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@splashcodex/api-key-manager)
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
9
|
+
- **Circuit Breaker** — Keys transition through `CLOSED → OPEN → HALF_OPEN → DEAD`
|
|
10
|
+
- **Error Classification** — Automatic detection of 429 (Quota), 403 (Auth), 5xx (Transient), Timeout, Safety blocks
|
|
11
|
+
- **Pluggable Strategies** — `StandardStrategy`, `WeightedStrategy`, `LatencyStrategy`
|
|
12
|
+
- **`execute()` Wrapper** — Single method: get key → call → latency → retry → fallback
|
|
13
|
+
- **Event Emitter** — Typed lifecycle hooks for monitoring & alerting
|
|
14
|
+
- **Auto-Retry with Backoff** — Built-in retry loop with exponential backoff + jitter
|
|
15
|
+
- **Request Timeout** — `AbortController`-based timeout per attempt
|
|
16
|
+
- **Fallback Function** — Graceful degradation when all keys fail
|
|
17
|
+
- **Provider Tagging** — Multi-provider routing (`openai`, `gemini`, etc.)
|
|
18
|
+
- **Health Checks** — Periodic key validation and auto-recovery
|
|
19
|
+
- **Bulkhead / Concurrency** — Limits concurrent `execute()` calls
|
|
20
|
+
- **State Persistence** — Survives restarts via pluggable storage
|
|
21
|
+
- **100% Backward Compatible** — v1.x and v2.x code works without changes
|
|
12
22
|
|
|
13
23
|
## Installation
|
|
14
24
|
|
|
@@ -16,65 +26,201 @@ A robust, universal API Key Rotation and Management system designed for high-ava
|
|
|
16
26
|
npm install @splashcodex/api-key-manager
|
|
17
27
|
```
|
|
18
28
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
### 1. Initialize
|
|
29
|
+
## Quick Start
|
|
22
30
|
|
|
23
31
|
```typescript
|
|
24
32
|
import { ApiKeyManager } from '@splashcodex/api-key-manager';
|
|
25
33
|
|
|
26
|
-
//
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"AIzaSy..."
|
|
31
|
-
];
|
|
34
|
+
// Simple (v1/v2 compatible)
|
|
35
|
+
const manager = new ApiKeyManager(['key1', 'key2', 'key3']);
|
|
36
|
+
const key = manager.getKey();
|
|
37
|
+
manager.markSuccess(key!);
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
// v3 — Full power
|
|
40
|
+
const result = await manager.execute(
|
|
41
|
+
(key) => fetch(`https://api.example.com?key=${key}`),
|
|
42
|
+
{ maxRetries: 3, timeoutMs: 5000 }
|
|
43
|
+
);
|
|
34
44
|
```
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
## v3.0 — execute() Wrapper
|
|
47
|
+
|
|
48
|
+
The star feature. Wraps the entire lifecycle into one method:
|
|
37
49
|
|
|
38
50
|
```typescript
|
|
39
|
-
const
|
|
51
|
+
const manager = new ApiKeyManager(keys, {
|
|
52
|
+
storage: localStorage,
|
|
53
|
+
strategy: new WeightedStrategy(),
|
|
54
|
+
fallbackFn: () => cachedResponse,
|
|
55
|
+
concurrency: 10
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const result = await manager.execute(
|
|
59
|
+
async (key, signal) => {
|
|
60
|
+
const res = await fetch(url, { headers: { 'x-api-key': key }, signal });
|
|
61
|
+
return res.json();
|
|
62
|
+
},
|
|
63
|
+
{ maxRetries: 3, timeoutMs: 10000 }
|
|
64
|
+
);
|
|
65
|
+
// Handles: key selection → timeout → retry → fallback → latency tracking
|
|
66
|
+
```
|
|
40
67
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
## Event Emitter
|
|
69
|
+
|
|
70
|
+
Monitor every state change:
|
|
44
71
|
|
|
45
|
-
|
|
46
|
-
|
|
72
|
+
```typescript
|
|
73
|
+
manager.on('keyDead', (key) => alertTeam(`Key ${key} permanently dead`));
|
|
74
|
+
manager.on('circuitOpen', (key) => metrics.increment('circuit_opens'));
|
|
75
|
+
manager.on('keyRecovered', (key) => log(`Key ${key} recovered`));
|
|
76
|
+
manager.on('retry', (key, attempt, delay) => log(`Retry #${attempt} in ${delay}ms`));
|
|
77
|
+
manager.on('fallback', (reason) => log(`Fallback triggered: ${reason}`));
|
|
78
|
+
manager.on('allKeysExhausted', () => alert('No healthy keys!'));
|
|
79
|
+
manager.on('bulkheadRejected', () => metrics.increment('rejected'));
|
|
80
|
+
manager.on('healthCheckPassed', (key) => log(`${key} healthy`));
|
|
81
|
+
manager.on('healthCheckFailed', (key, err) => log(`${key} unhealthy`));
|
|
47
82
|
```
|
|
48
83
|
|
|
49
|
-
|
|
84
|
+
## Load Balancing Strategies
|
|
50
85
|
|
|
51
|
-
|
|
86
|
+
### Weighted (Cost Optimization)
|
|
52
87
|
|
|
53
88
|
```typescript
|
|
54
|
-
|
|
55
|
-
|
|
89
|
+
import { ApiKeyManager, WeightedStrategy } from '@splashcodex/api-key-manager';
|
|
90
|
+
|
|
91
|
+
const manager = new ApiKeyManager(
|
|
92
|
+
[
|
|
93
|
+
{ key: 'free-key-1', weight: 1.0 },
|
|
94
|
+
{ key: 'free-key-2', weight: 1.0 },
|
|
95
|
+
{ key: 'paid-backup', weight: 0.1 },
|
|
96
|
+
],
|
|
97
|
+
{ strategy: new WeightedStrategy() }
|
|
98
|
+
);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Latency (Performance)
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { ApiKeyManager, LatencyStrategy } from '@splashcodex/api-key-manager';
|
|
105
|
+
|
|
106
|
+
const manager = new ApiKeyManager(keys, { strategy: new LatencyStrategy() });
|
|
107
|
+
// After execute(), latency is tracked automatically
|
|
108
|
+
```
|
|
56
109
|
|
|
57
|
-
|
|
58
|
-
manager.markSuccess(key);
|
|
110
|
+
## Provider Tagging
|
|
59
111
|
|
|
60
|
-
|
|
112
|
+
Route requests to specific providers:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const manager = new ApiKeyManager([
|
|
116
|
+
{ key: 'sk-openai-1', weight: 1.0, provider: 'openai' },
|
|
117
|
+
{ key: 'sk-openai-2', weight: 1.0, provider: 'openai' },
|
|
118
|
+
{ key: 'AIza-gemini', weight: 0.5, provider: 'gemini' },
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
const openaiKey = manager.getKeyByProvider('openai');
|
|
122
|
+
const geminiKey = manager.getKeyByProvider('gemini');
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Health Checks
|
|
126
|
+
|
|
127
|
+
Proactively detect recovered keys:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
manager.setHealthCheck(async (key) => {
|
|
131
|
+
const res = await fetch(`https://api.openai.com/v1/models`, {
|
|
132
|
+
headers: { Authorization: `Bearer ${key}` }
|
|
133
|
+
});
|
|
134
|
+
return res.ok;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
manager.startHealthChecks(60_000); // Check every 60 seconds
|
|
138
|
+
// manager.stopHealthChecks(); // Stop when done
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Error Handling
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
try {
|
|
145
|
+
const result = await callApi(key);
|
|
146
|
+
manager.markSuccess(key, duration);
|
|
61
147
|
} catch (error) {
|
|
62
|
-
// ❌ REPORT FAILURE
|
|
63
|
-
// The manager will automatically classify the error (Quota vs Auth vs Transient)
|
|
64
148
|
const classification = manager.classifyError(error);
|
|
65
149
|
manager.markFailed(key, classification);
|
|
66
150
|
|
|
67
|
-
|
|
151
|
+
if (classification.retryable) {
|
|
152
|
+
const delay = manager.calculateBackoff(attempt);
|
|
153
|
+
await sleep(delay);
|
|
154
|
+
}
|
|
68
155
|
}
|
|
69
156
|
```
|
|
70
157
|
|
|
71
|
-
##
|
|
158
|
+
## API Reference
|
|
159
|
+
|
|
160
|
+
### Constructor
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// Legacy (v1/v2)
|
|
164
|
+
new ApiKeyManager(keys, storage?, strategy?)
|
|
165
|
+
|
|
166
|
+
// v3 Options
|
|
167
|
+
new ApiKeyManager(keys, {
|
|
168
|
+
storage?, // Pluggable storage { getItem, setItem }
|
|
169
|
+
strategy?, // LoadBalancingStrategy instance
|
|
170
|
+
fallbackFn?, // () => any — called when all keys exhausted
|
|
171
|
+
concurrency?, // Max concurrent execute() calls
|
|
172
|
+
})
|
|
173
|
+
```
|
|
72
174
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
175
|
+
### Methods
|
|
176
|
+
|
|
177
|
+
| Method | Description |
|
|
178
|
+
|--------|-------------|
|
|
179
|
+
| `getKey()` | Returns best available key via strategy |
|
|
180
|
+
| `getKeyByProvider(provider)` | Get key filtered by provider tag |
|
|
181
|
+
| `markSuccess(key, durationMs?)` | Report success + optional latency |
|
|
182
|
+
| `markFailed(key, classification)` | Report failure with error type |
|
|
183
|
+
| `classifyError(error, finishReason?)` | Classify an error automatically |
|
|
184
|
+
| `execute(fn, options?)` | Full lifecycle wrapper with retry/timeout |
|
|
185
|
+
| `calculateBackoff(attempt)` | Get backoff delay with jitter |
|
|
186
|
+
| `getStats()` | Get pool health statistics |
|
|
187
|
+
| `getKeyCount()` | Count of non-DEAD keys |
|
|
188
|
+
| `setHealthCheck(fn)` | Set health check function |
|
|
189
|
+
| `startHealthChecks(ms)` | Start periodic health checks |
|
|
190
|
+
| `stopHealthChecks()` | Stop health checks |
|
|
191
|
+
|
|
192
|
+
### Events
|
|
193
|
+
|
|
194
|
+
| Event | Payload | Trigger |
|
|
195
|
+
|-------|---------|---------|
|
|
196
|
+
| `keyDead` | `key: string` | Key marked as permanently dead |
|
|
197
|
+
| `circuitOpen` | `key: string` | Key circuit opened (cooldown) |
|
|
198
|
+
| `circuitHalfOpen` | `key: string` | Key entering test phase |
|
|
199
|
+
| `keyRecovered` | `key: string` | Key recovered from failure |
|
|
200
|
+
| `fallback` | `reason: string` | Fallback function invoked |
|
|
201
|
+
| `allKeysExhausted` | — | All keys dead, no fallback |
|
|
202
|
+
| `retry` | `key, attempt, delayMs` | Retry attempt starting |
|
|
203
|
+
| `executeSuccess` | `key, durationMs` | execute() completed successfully |
|
|
204
|
+
| `executeFailed` | `key, error` | execute() attempt failed |
|
|
205
|
+
| `bulkheadRejected` | — | Concurrency limit reached |
|
|
206
|
+
| `healthCheckPassed` | `key: string` | Health check succeeded |
|
|
207
|
+
| `healthCheckFailed` | `key, error` | Health check failed |
|
|
208
|
+
|
|
209
|
+
### Custom Errors
|
|
210
|
+
|
|
211
|
+
| Error | When |
|
|
212
|
+
|-------|------|
|
|
213
|
+
| `TimeoutError` | Request exceeded `timeoutMs` |
|
|
214
|
+
| `BulkheadRejectionError` | Concurrency limit exceeded |
|
|
215
|
+
| `AllKeysExhaustedError` | All keys dead, no fallback |
|
|
216
|
+
|
|
217
|
+
### Strategies
|
|
218
|
+
|
|
219
|
+
| Strategy | Algorithm | Best For |
|
|
220
|
+
|----------|-----------|----------|
|
|
221
|
+
| `StandardStrategy` | Least Failures → LRU | General use |
|
|
222
|
+
| `WeightedStrategy` | Probabilistic by weight | Cost optimization |
|
|
223
|
+
| `LatencyStrategy` | Lowest avg latency | Performance |
|
|
78
224
|
|
|
79
225
|
## License
|
|
80
226
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Universal ApiKeyManager
|
|
3
|
-
* Implements: Rotation, Circuit Breaker, Persistence, Exponential Backoff
|
|
2
|
+
* Universal ApiKeyManager v3.0
|
|
3
|
+
* Implements: Rotation, Circuit Breaker, Persistence, Exponential Backoff, Strategies,
|
|
4
|
+
* Event Emitter, Fallback, execute(), Timeout, Auto-Retry, Provider Tags,
|
|
5
|
+
* Health Checks, Bulkhead/Concurrency
|
|
4
6
|
* Gemini-Specific: finishReason handling, Safety blocks, RECITATION detection
|
|
5
7
|
*/
|
|
8
|
+
import { EventEmitter } from 'events';
|
|
6
9
|
export interface KeyState {
|
|
7
10
|
key: string;
|
|
8
11
|
failCount: number;
|
|
@@ -14,8 +17,13 @@ export interface KeyState {
|
|
|
14
17
|
totalRequests: number;
|
|
15
18
|
halfOpenTestTime: number | null;
|
|
16
19
|
customCooldown: number | null;
|
|
20
|
+
weight: number;
|
|
21
|
+
averageLatency: number;
|
|
22
|
+
totalLatency: number;
|
|
23
|
+
latencySamples: number;
|
|
24
|
+
provider: string;
|
|
17
25
|
}
|
|
18
|
-
export type ErrorType = 'QUOTA' | 'TRANSIENT' | 'AUTH' | 'BAD_REQUEST' | 'SAFETY' | 'RECITATION' | 'UNKNOWN';
|
|
26
|
+
export type ErrorType = 'QUOTA' | 'TRANSIENT' | 'AUTH' | 'BAD_REQUEST' | 'SAFETY' | 'RECITATION' | 'TIMEOUT' | 'UNKNOWN';
|
|
19
27
|
export interface ErrorClassification {
|
|
20
28
|
type: ErrorType;
|
|
21
29
|
retryable: boolean;
|
|
@@ -29,55 +37,138 @@ export interface ApiKeyManagerStats {
|
|
|
29
37
|
cooling: number;
|
|
30
38
|
dead: number;
|
|
31
39
|
}
|
|
32
|
-
export
|
|
40
|
+
export interface ExecuteOptions {
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
maxRetries?: number;
|
|
43
|
+
finishReason?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ApiKeyManagerOptions {
|
|
46
|
+
storage?: any;
|
|
47
|
+
strategy?: LoadBalancingStrategy;
|
|
48
|
+
fallbackFn?: () => any;
|
|
49
|
+
concurrency?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface ApiKeyManagerEventMap {
|
|
52
|
+
keyDead: (key: string) => void;
|
|
53
|
+
circuitOpen: (key: string) => void;
|
|
54
|
+
circuitHalfOpen: (key: string) => void;
|
|
55
|
+
keyRecovered: (key: string) => void;
|
|
56
|
+
fallback: (reason: string) => void;
|
|
57
|
+
allKeysExhausted: () => void;
|
|
58
|
+
retry: (key: string, attempt: number, delayMs: number) => void;
|
|
59
|
+
healthCheckFailed: (key: string, error: any) => void;
|
|
60
|
+
healthCheckPassed: (key: string) => void;
|
|
61
|
+
executeSuccess: (key: string, durationMs: number) => void;
|
|
62
|
+
executeFailed: (key: string, error: any) => void;
|
|
63
|
+
bulkheadRejected: () => void;
|
|
64
|
+
}
|
|
65
|
+
export declare class TimeoutError extends Error {
|
|
66
|
+
constructor(ms: number);
|
|
67
|
+
}
|
|
68
|
+
export declare class BulkheadRejectionError extends Error {
|
|
69
|
+
constructor();
|
|
70
|
+
}
|
|
71
|
+
export declare class AllKeysExhaustedError extends Error {
|
|
72
|
+
constructor();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Strategy Interface for selecting the next key
|
|
76
|
+
*/
|
|
77
|
+
export interface LoadBalancingStrategy {
|
|
78
|
+
next(candidates: KeyState[]): KeyState | null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Standard Strategy: Least Failed > Least Recently Used
|
|
82
|
+
*/
|
|
83
|
+
export declare class StandardStrategy implements LoadBalancingStrategy {
|
|
84
|
+
next(candidates: KeyState[]): KeyState | null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Weighted Strategy: Probabilistic selection based on weight
|
|
88
|
+
* Higher weight = Higher chance of selection
|
|
89
|
+
*/
|
|
90
|
+
export declare class WeightedStrategy implements LoadBalancingStrategy {
|
|
91
|
+
next(candidates: KeyState[]): KeyState | null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Latency Strategy: Pick lowest average latency
|
|
95
|
+
*/
|
|
96
|
+
export declare class LatencyStrategy implements LoadBalancingStrategy {
|
|
97
|
+
next(candidates: KeyState[]): KeyState | null;
|
|
98
|
+
}
|
|
99
|
+
export declare class ApiKeyManager extends EventEmitter {
|
|
33
100
|
private keys;
|
|
34
101
|
private storageKey;
|
|
35
102
|
private storage;
|
|
36
|
-
|
|
103
|
+
private strategy;
|
|
104
|
+
private fallbackFn?;
|
|
105
|
+
private maxConcurrency;
|
|
106
|
+
private activeCalls;
|
|
107
|
+
private healthCheckFn?;
|
|
108
|
+
private healthCheckInterval?;
|
|
37
109
|
/**
|
|
38
|
-
*
|
|
110
|
+
* Constructor supports both legacy positional args and new options object.
|
|
111
|
+
*
|
|
112
|
+
* @example Legacy (v1/v2 — still works):
|
|
113
|
+
* new ApiKeyManager(['key1', 'key2'], storage, strategy)
|
|
114
|
+
*
|
|
115
|
+
* @example New (v3):
|
|
116
|
+
* new ApiKeyManager(keys, { storage, strategy, fallbackFn, concurrency })
|
|
39
117
|
*/
|
|
40
|
-
|
|
118
|
+
constructor(initialKeys: string[] | {
|
|
119
|
+
key: string;
|
|
120
|
+
weight?: number;
|
|
121
|
+
provider?: string;
|
|
122
|
+
}[], storageOrOptions?: any | ApiKeyManagerOptions, strategy?: LoadBalancingStrategy);
|
|
41
123
|
/**
|
|
42
|
-
*
|
|
124
|
+
* CLASSIFIES an error to determine handling strategy
|
|
43
125
|
*/
|
|
126
|
+
classifyError(error: any, finishReason?: string): ErrorClassification;
|
|
44
127
|
private parseRetryAfter;
|
|
45
|
-
/**
|
|
46
|
-
* HEALTH CHECK
|
|
47
|
-
* Determines if a key is usable based on Circuit Breaker logic
|
|
48
|
-
*/
|
|
49
128
|
private isOnCooldown;
|
|
50
|
-
/**
|
|
51
|
-
* CORE ROTATION LOGIC
|
|
52
|
-
* Returns the best available key
|
|
53
|
-
*/
|
|
54
129
|
getKey(): string | null;
|
|
55
130
|
/**
|
|
56
|
-
* Get
|
|
131
|
+
* Get a key filtered by provider tag
|
|
57
132
|
*/
|
|
133
|
+
getKeyByProvider(provider: string): string | null;
|
|
58
134
|
getKeyCount(): number;
|
|
59
135
|
/**
|
|
60
|
-
*
|
|
136
|
+
* Mark success AND update latency stats
|
|
137
|
+
* @param durationMs Duration of the request in milliseconds
|
|
61
138
|
*/
|
|
62
|
-
markSuccess(key: string): void;
|
|
139
|
+
markSuccess(key: string, durationMs?: number): void;
|
|
140
|
+
markFailed(key: string, classification: ErrorClassification): void;
|
|
141
|
+
markFailedLegacy(key: string, isQuota?: boolean): void;
|
|
142
|
+
calculateBackoff(attempt: number): number;
|
|
143
|
+
getStats(): ApiKeyManagerStats;
|
|
144
|
+
_getKeys(): KeyState[];
|
|
63
145
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
146
|
+
* Wraps the entire API call lifecycle into a single method.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* const result = await manager.execute(
|
|
150
|
+
* (key) => fetch(`https://api.example.com?key=${key}`),
|
|
151
|
+
* { maxRetries: 3, timeoutMs: 5000 }
|
|
152
|
+
* );
|
|
66
153
|
*/
|
|
67
|
-
|
|
154
|
+
execute<T>(fn: (key: string, signal?: AbortSignal) => Promise<T>, options?: ExecuteOptions): Promise<T>;
|
|
155
|
+
private _executeWithRetry;
|
|
156
|
+
private _executeWithTimeout;
|
|
157
|
+
private _sleep;
|
|
68
158
|
/**
|
|
69
|
-
*
|
|
159
|
+
* Set a health check function that tests if a key is operational
|
|
70
160
|
*/
|
|
71
|
-
|
|
161
|
+
setHealthCheck(fn: (key: string) => Promise<boolean>): void;
|
|
72
162
|
/**
|
|
73
|
-
*
|
|
163
|
+
* Start periodic health checks
|
|
164
|
+
* @param intervalMs How often to run health checks (default: 60s)
|
|
74
165
|
*/
|
|
75
|
-
|
|
166
|
+
startHealthChecks(intervalMs?: number): void;
|
|
76
167
|
/**
|
|
77
|
-
*
|
|
168
|
+
* Stop periodic health checks
|
|
78
169
|
*/
|
|
79
|
-
|
|
80
|
-
|
|
170
|
+
stopHealthChecks(): void;
|
|
171
|
+
private _runHealthChecks;
|
|
81
172
|
private saveState;
|
|
82
173
|
private loadState;
|
|
83
174
|
}
|