@push.rocks/smartproxy 19.5.4 → 19.5.6
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_ts/core/utils/async-utils.d.ts +81 -0
- package/dist_ts/core/utils/async-utils.js +216 -0
- package/dist_ts/core/utils/binary-heap.d.ts +73 -0
- package/dist_ts/core/utils/binary-heap.js +193 -0
- package/dist_ts/core/utils/enhanced-connection-pool.d.ts +110 -0
- package/dist_ts/core/utils/enhanced-connection-pool.js +320 -0
- package/dist_ts/core/utils/fs-utils.d.ts +144 -0
- package/dist_ts/core/utils/fs-utils.js +252 -0
- package/dist_ts/core/utils/index.d.ts +6 -2
- package/dist_ts/core/utils/index.js +7 -3
- package/dist_ts/core/utils/lifecycle-component.d.ts +59 -0
- package/dist_ts/core/utils/lifecycle-component.js +195 -0
- package/dist_ts/core/utils/socket-utils.d.ts +28 -0
- package/dist_ts/core/utils/socket-utils.js +77 -0
- package/dist_ts/forwarding/handlers/http-handler.js +7 -4
- package/dist_ts/forwarding/handlers/https-passthrough-handler.js +14 -55
- package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.js +52 -40
- package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.js +31 -43
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/dist_ts/proxies/http-proxy/certificate-manager.d.ts +15 -0
- package/dist_ts/proxies/http-proxy/certificate-manager.js +49 -2
- package/dist_ts/proxies/http-proxy/connection-pool.js +4 -19
- package/dist_ts/proxies/http-proxy/http-proxy.js +3 -7
- package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +10 -0
- package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +53 -43
- package/dist_ts/proxies/smart-proxy/cert-store.js +22 -20
- package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +35 -9
- package/dist_ts/proxies/smart-proxy/connection-manager.js +243 -189
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +13 -2
- package/dist_ts/proxies/smart-proxy/port-manager.js +3 -3
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +35 -4
- package/package.json +2 -2
- package/readme.hints.md +96 -1
- package/readme.plan.md +1135 -221
- package/readme.problems.md +167 -83
- package/ts/core/utils/async-utils.ts +275 -0
- package/ts/core/utils/binary-heap.ts +225 -0
- package/ts/core/utils/enhanced-connection-pool.ts +420 -0
- package/ts/core/utils/fs-utils.ts +270 -0
- package/ts/core/utils/index.ts +6 -2
- package/ts/core/utils/lifecycle-component.ts +231 -0
- package/ts/core/utils/socket-utils.ts +96 -0
- package/ts/forwarding/handlers/http-handler.ts +7 -3
- package/ts/forwarding/handlers/https-passthrough-handler.ts +13 -62
- package/ts/forwarding/handlers/https-terminate-to-http-handler.ts +58 -46
- package/ts/forwarding/handlers/https-terminate-to-https-handler.ts +38 -53
- package/ts/plugins.ts +2 -1
- package/ts/proxies/http-proxy/certificate-manager.ts +52 -1
- package/ts/proxies/http-proxy/connection-pool.ts +3 -16
- package/ts/proxies/http-proxy/http-proxy.ts +2 -5
- package/ts/proxies/nftables-proxy/nftables-proxy.ts +64 -79
- package/ts/proxies/smart-proxy/cert-store.ts +26 -20
- package/ts/proxies/smart-proxy/connection-manager.ts +277 -197
- package/ts/proxies/smart-proxy/http-proxy-bridge.ts +15 -1
- package/ts/proxies/smart-proxy/port-manager.ts +2 -2
- package/ts/proxies/smart-proxy/route-connection-handler.ts +39 -4
- package/readme.plan2.md +0 -764
- package/ts/common/eventUtils.ts +0 -34
- package/ts/common/types.ts +0 -91
- package/ts/core/utils/event-system.ts +0 -376
- package/ts/core/utils/event-utils.ts +0 -25
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async utility functions for SmartProxy
|
|
3
|
+
* Provides non-blocking alternatives to synchronous operations
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Delays execution for the specified number of milliseconds
|
|
7
|
+
* Non-blocking alternative to busy wait loops
|
|
8
|
+
* @param ms - Number of milliseconds to delay
|
|
9
|
+
* @returns Promise that resolves after the delay
|
|
10
|
+
*/
|
|
11
|
+
export declare function delay(ms: number): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Retry an async operation with exponential backoff
|
|
14
|
+
* @param fn - The async function to retry
|
|
15
|
+
* @param options - Retry options
|
|
16
|
+
* @returns The result of the function or throws the last error
|
|
17
|
+
*/
|
|
18
|
+
export declare function retryWithBackoff<T>(fn: () => Promise<T>, options?: {
|
|
19
|
+
maxAttempts?: number;
|
|
20
|
+
initialDelay?: number;
|
|
21
|
+
maxDelay?: number;
|
|
22
|
+
factor?: number;
|
|
23
|
+
onRetry?: (attempt: number, error: Error) => void;
|
|
24
|
+
}): Promise<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Execute an async operation with a timeout
|
|
27
|
+
* @param fn - The async function to execute
|
|
28
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
29
|
+
* @param timeoutError - Optional custom timeout error
|
|
30
|
+
* @returns The result of the function or throws timeout error
|
|
31
|
+
*/
|
|
32
|
+
export declare function withTimeout<T>(fn: () => Promise<T>, timeoutMs: number, timeoutError?: Error): Promise<T>;
|
|
33
|
+
/**
|
|
34
|
+
* Run multiple async operations in parallel with a concurrency limit
|
|
35
|
+
* @param items - Array of items to process
|
|
36
|
+
* @param fn - Async function to run for each item
|
|
37
|
+
* @param concurrency - Maximum number of concurrent operations
|
|
38
|
+
* @returns Array of results in the same order as input
|
|
39
|
+
*/
|
|
40
|
+
export declare function parallelLimit<T, R>(items: T[], fn: (item: T, index: number) => Promise<R>, concurrency: number): Promise<R[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Debounce an async function
|
|
43
|
+
* @param fn - The async function to debounce
|
|
44
|
+
* @param delayMs - Delay in milliseconds
|
|
45
|
+
* @returns Debounced function with cancel method
|
|
46
|
+
*/
|
|
47
|
+
export declare function debounceAsync<T extends (...args: any[]) => Promise<any>>(fn: T, delayMs: number): T & {
|
|
48
|
+
cancel: () => void;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Create a mutex for ensuring exclusive access to a resource
|
|
52
|
+
*/
|
|
53
|
+
export declare class AsyncMutex {
|
|
54
|
+
private queue;
|
|
55
|
+
private locked;
|
|
56
|
+
acquire(): Promise<() => void>;
|
|
57
|
+
private release;
|
|
58
|
+
runExclusive<T>(fn: () => Promise<T>): Promise<T>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Circuit breaker for protecting against cascading failures
|
|
62
|
+
*/
|
|
63
|
+
export declare class CircuitBreaker {
|
|
64
|
+
private options;
|
|
65
|
+
private failureCount;
|
|
66
|
+
private lastFailureTime;
|
|
67
|
+
private state;
|
|
68
|
+
constructor(options: {
|
|
69
|
+
failureThreshold: number;
|
|
70
|
+
resetTimeout: number;
|
|
71
|
+
onStateChange?: (state: 'closed' | 'open' | 'half-open') => void;
|
|
72
|
+
});
|
|
73
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
74
|
+
private onSuccess;
|
|
75
|
+
private onFailure;
|
|
76
|
+
private setState;
|
|
77
|
+
isOpen(): boolean;
|
|
78
|
+
getState(): 'closed' | 'open' | 'half-open';
|
|
79
|
+
recordSuccess(): void;
|
|
80
|
+
recordFailure(): void;
|
|
81
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async utility functions for SmartProxy
|
|
3
|
+
* Provides non-blocking alternatives to synchronous operations
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Delays execution for the specified number of milliseconds
|
|
7
|
+
* Non-blocking alternative to busy wait loops
|
|
8
|
+
* @param ms - Number of milliseconds to delay
|
|
9
|
+
* @returns Promise that resolves after the delay
|
|
10
|
+
*/
|
|
11
|
+
export async function delay(ms) {
|
|
12
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Retry an async operation with exponential backoff
|
|
16
|
+
* @param fn - The async function to retry
|
|
17
|
+
* @param options - Retry options
|
|
18
|
+
* @returns The result of the function or throws the last error
|
|
19
|
+
*/
|
|
20
|
+
export async function retryWithBackoff(fn, options = {}) {
|
|
21
|
+
const { maxAttempts = 3, initialDelay = 100, maxDelay = 10000, factor = 2, onRetry } = options;
|
|
22
|
+
let lastError = null;
|
|
23
|
+
let currentDelay = initialDelay;
|
|
24
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
25
|
+
try {
|
|
26
|
+
return await fn();
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
lastError = error;
|
|
30
|
+
if (attempt === maxAttempts) {
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
if (onRetry) {
|
|
34
|
+
onRetry(attempt, error);
|
|
35
|
+
}
|
|
36
|
+
await delay(currentDelay);
|
|
37
|
+
currentDelay = Math.min(currentDelay * factor, maxDelay);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw lastError || new Error('Retry failed');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Execute an async operation with a timeout
|
|
44
|
+
* @param fn - The async function to execute
|
|
45
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
46
|
+
* @param timeoutError - Optional custom timeout error
|
|
47
|
+
* @returns The result of the function or throws timeout error
|
|
48
|
+
*/
|
|
49
|
+
export async function withTimeout(fn, timeoutMs, timeoutError) {
|
|
50
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
reject(timeoutError || new Error(`Operation timed out after ${timeoutMs}ms`));
|
|
53
|
+
}, timeoutMs);
|
|
54
|
+
});
|
|
55
|
+
return Promise.race([fn(), timeoutPromise]);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Run multiple async operations in parallel with a concurrency limit
|
|
59
|
+
* @param items - Array of items to process
|
|
60
|
+
* @param fn - Async function to run for each item
|
|
61
|
+
* @param concurrency - Maximum number of concurrent operations
|
|
62
|
+
* @returns Array of results in the same order as input
|
|
63
|
+
*/
|
|
64
|
+
export async function parallelLimit(items, fn, concurrency) {
|
|
65
|
+
const results = new Array(items.length);
|
|
66
|
+
const executing = new Set();
|
|
67
|
+
for (let i = 0; i < items.length; i++) {
|
|
68
|
+
const promise = fn(items[i], i).then(result => {
|
|
69
|
+
results[i] = result;
|
|
70
|
+
executing.delete(promise);
|
|
71
|
+
});
|
|
72
|
+
executing.add(promise);
|
|
73
|
+
if (executing.size >= concurrency) {
|
|
74
|
+
await Promise.race(executing);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
await Promise.all(executing);
|
|
78
|
+
return results;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Debounce an async function
|
|
82
|
+
* @param fn - The async function to debounce
|
|
83
|
+
* @param delayMs - Delay in milliseconds
|
|
84
|
+
* @returns Debounced function with cancel method
|
|
85
|
+
*/
|
|
86
|
+
export function debounceAsync(fn, delayMs) {
|
|
87
|
+
let timeoutId = null;
|
|
88
|
+
let lastPromise = null;
|
|
89
|
+
const debounced = ((...args) => {
|
|
90
|
+
if (timeoutId) {
|
|
91
|
+
clearTimeout(timeoutId);
|
|
92
|
+
}
|
|
93
|
+
lastPromise = new Promise((resolve, reject) => {
|
|
94
|
+
timeoutId = setTimeout(async () => {
|
|
95
|
+
timeoutId = null;
|
|
96
|
+
try {
|
|
97
|
+
const result = await fn(...args);
|
|
98
|
+
resolve(result);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
reject(error);
|
|
102
|
+
}
|
|
103
|
+
}, delayMs);
|
|
104
|
+
});
|
|
105
|
+
return lastPromise;
|
|
106
|
+
});
|
|
107
|
+
debounced.cancel = () => {
|
|
108
|
+
if (timeoutId) {
|
|
109
|
+
clearTimeout(timeoutId);
|
|
110
|
+
timeoutId = null;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return debounced;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Create a mutex for ensuring exclusive access to a resource
|
|
117
|
+
*/
|
|
118
|
+
export class AsyncMutex {
|
|
119
|
+
constructor() {
|
|
120
|
+
this.queue = [];
|
|
121
|
+
this.locked = false;
|
|
122
|
+
}
|
|
123
|
+
async acquire() {
|
|
124
|
+
if (!this.locked) {
|
|
125
|
+
this.locked = true;
|
|
126
|
+
return () => this.release();
|
|
127
|
+
}
|
|
128
|
+
return new Promise(resolve => {
|
|
129
|
+
this.queue.push(() => {
|
|
130
|
+
resolve(() => this.release());
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
release() {
|
|
135
|
+
const next = this.queue.shift();
|
|
136
|
+
if (next) {
|
|
137
|
+
next();
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
this.locked = false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async runExclusive(fn) {
|
|
144
|
+
const release = await this.acquire();
|
|
145
|
+
try {
|
|
146
|
+
return await fn();
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
release();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Circuit breaker for protecting against cascading failures
|
|
155
|
+
*/
|
|
156
|
+
export class CircuitBreaker {
|
|
157
|
+
constructor(options) {
|
|
158
|
+
this.options = options;
|
|
159
|
+
this.failureCount = 0;
|
|
160
|
+
this.lastFailureTime = 0;
|
|
161
|
+
this.state = 'closed';
|
|
162
|
+
}
|
|
163
|
+
async execute(fn) {
|
|
164
|
+
if (this.state === 'open') {
|
|
165
|
+
if (Date.now() - this.lastFailureTime > this.options.resetTimeout) {
|
|
166
|
+
this.setState('half-open');
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
throw new Error('Circuit breaker is open');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const result = await fn();
|
|
174
|
+
this.onSuccess();
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
this.onFailure();
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
onSuccess() {
|
|
183
|
+
this.failureCount = 0;
|
|
184
|
+
if (this.state !== 'closed') {
|
|
185
|
+
this.setState('closed');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
onFailure() {
|
|
189
|
+
this.failureCount++;
|
|
190
|
+
this.lastFailureTime = Date.now();
|
|
191
|
+
if (this.failureCount >= this.options.failureThreshold) {
|
|
192
|
+
this.setState('open');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
setState(state) {
|
|
196
|
+
if (this.state !== state) {
|
|
197
|
+
this.state = state;
|
|
198
|
+
if (this.options.onStateChange) {
|
|
199
|
+
this.options.onStateChange(state);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
isOpen() {
|
|
204
|
+
return this.state === 'open';
|
|
205
|
+
}
|
|
206
|
+
getState() {
|
|
207
|
+
return this.state;
|
|
208
|
+
}
|
|
209
|
+
recordSuccess() {
|
|
210
|
+
this.onSuccess();
|
|
211
|
+
}
|
|
212
|
+
recordFailure() {
|
|
213
|
+
this.onFailure();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3V0aWxzL2FzeW5jLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVIOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUNwQyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3pELENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZ0JBQWdCLENBQ3BDLEVBQW9CLEVBQ3BCLFVBTUksRUFBRTtJQUVOLE1BQU0sRUFDSixXQUFXLEdBQUcsQ0FBQyxFQUNmLFlBQVksR0FBRyxHQUFHLEVBQ2xCLFFBQVEsR0FBRyxLQUFLLEVBQ2hCLE1BQU0sR0FBRyxDQUFDLEVBQ1YsT0FBTyxFQUNSLEdBQUcsT0FBTyxDQUFDO0lBRVosSUFBSSxTQUFTLEdBQWlCLElBQUksQ0FBQztJQUNuQyxJQUFJLFlBQVksR0FBRyxZQUFZLENBQUM7SUFFaEMsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxJQUFJLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ3hELElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUNwQixDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixTQUFTLEdBQUcsS0FBSyxDQUFDO1lBRWxCLElBQUksT0FBTyxLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUM1QixNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFFRCxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLE9BQU8sQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDMUIsQ0FBQztZQUVELE1BQU0sS0FBSyxDQUFDLFlB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
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A binary heap implementation for efficient priority queue operations
|
|
3
|
+
* Supports O(log n) insert and extract operations
|
|
4
|
+
*/
|
|
5
|
+
export declare class BinaryHeap<T> {
|
|
6
|
+
private compareFn;
|
|
7
|
+
private extractKey?;
|
|
8
|
+
private heap;
|
|
9
|
+
private keyMap?;
|
|
10
|
+
constructor(compareFn: (a: T, b: T) => number, extractKey?: (item: T) => string);
|
|
11
|
+
/**
|
|
12
|
+
* Get the current size of the heap
|
|
13
|
+
*/
|
|
14
|
+
get size(): number;
|
|
15
|
+
/**
|
|
16
|
+
* Check if the heap is empty
|
|
17
|
+
*/
|
|
18
|
+
isEmpty(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Peek at the top element without removing it
|
|
21
|
+
*/
|
|
22
|
+
peek(): T | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Insert a new item into the heap
|
|
25
|
+
* O(log n) time complexity
|
|
26
|
+
*/
|
|
27
|
+
insert(item: T): void;
|
|
28
|
+
/**
|
|
29
|
+
* Extract the top element from the heap
|
|
30
|
+
* O(log n) time complexity
|
|
31
|
+
*/
|
|
32
|
+
extract(): T | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Extract an element that matches the predicate
|
|
35
|
+
* O(n) time complexity for search, O(log n) for extraction
|
|
36
|
+
*/
|
|
37
|
+
extractIf(predicate: (item: T) => boolean): T | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Extract an element by its key (if extractKey was provided)
|
|
40
|
+
* O(log n) time complexity
|
|
41
|
+
*/
|
|
42
|
+
extractByKey(key: string): T | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Check if a key exists in the heap
|
|
45
|
+
* O(1) time complexity
|
|
46
|
+
*/
|
|
47
|
+
hasKey(key: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Get all elements as an array (does not modify heap)
|
|
50
|
+
* O(n) time complexity
|
|
51
|
+
*/
|
|
52
|
+
toArray(): T[];
|
|
53
|
+
/**
|
|
54
|
+
* Clear the heap
|
|
55
|
+
*/
|
|
56
|
+
clear(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Extract element at specific index
|
|
59
|
+
*/
|
|
60
|
+
private extractAt;
|
|
61
|
+
/**
|
|
62
|
+
* Bubble up element at given index to maintain heap property
|
|
63
|
+
*/
|
|
64
|
+
private bubbleUp;
|
|
65
|
+
/**
|
|
66
|
+
* Bubble down element at given index to maintain heap property
|
|
67
|
+
*/
|
|
68
|
+
private bubbleDown;
|
|
69
|
+
/**
|
|
70
|
+
* Swap two elements in the heap
|
|
71
|
+
*/
|
|
72
|
+
private swap;
|
|
73
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A binary heap implementation for efficient priority queue operations
|
|
3
|
+
* Supports O(log n) insert and extract operations
|
|
4
|
+
*/
|
|
5
|
+
export class BinaryHeap {
|
|
6
|
+
constructor(compareFn, extractKey) {
|
|
7
|
+
this.compareFn = compareFn;
|
|
8
|
+
this.extractKey = extractKey;
|
|
9
|
+
this.heap = [];
|
|
10
|
+
if (extractKey) {
|
|
11
|
+
this.keyMap = new Map();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get the current size of the heap
|
|
16
|
+
*/
|
|
17
|
+
get size() {
|
|
18
|
+
return this.heap.length;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if the heap is empty
|
|
22
|
+
*/
|
|
23
|
+
isEmpty() {
|
|
24
|
+
return this.heap.length === 0;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Peek at the top element without removing it
|
|
28
|
+
*/
|
|
29
|
+
peek() {
|
|
30
|
+
return this.heap[0];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Insert a new item into the heap
|
|
34
|
+
* O(log n) time complexity
|
|
35
|
+
*/
|
|
36
|
+
insert(item) {
|
|
37
|
+
const index = this.heap.length;
|
|
38
|
+
this.heap.push(item);
|
|
39
|
+
if (this.keyMap && this.extractKey) {
|
|
40
|
+
const key = this.extractKey(item);
|
|
41
|
+
this.keyMap.set(key, index);
|
|
42
|
+
}
|
|
43
|
+
this.bubbleUp(index);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Extract the top element from the heap
|
|
47
|
+
* O(log n) time complexity
|
|
48
|
+
*/
|
|
49
|
+
extract() {
|
|
50
|
+
if (this.heap.length === 0)
|
|
51
|
+
return undefined;
|
|
52
|
+
if (this.heap.length === 1) {
|
|
53
|
+
const item = this.heap.pop();
|
|
54
|
+
if (this.keyMap && this.extractKey) {
|
|
55
|
+
this.keyMap.delete(this.extractKey(item));
|
|
56
|
+
}
|
|
57
|
+
return item;
|
|
58
|
+
}
|
|
59
|
+
const result = this.heap[0];
|
|
60
|
+
const lastItem = this.heap.pop();
|
|
61
|
+
this.heap[0] = lastItem;
|
|
62
|
+
if (this.keyMap && this.extractKey) {
|
|
63
|
+
this.keyMap.delete(this.extractKey(result));
|
|
64
|
+
this.keyMap.set(this.extractKey(lastItem), 0);
|
|
65
|
+
}
|
|
66
|
+
this.bubbleDown(0);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract an element that matches the predicate
|
|
71
|
+
* O(n) time complexity for search, O(log n) for extraction
|
|
72
|
+
*/
|
|
73
|
+
extractIf(predicate) {
|
|
74
|
+
const index = this.heap.findIndex(predicate);
|
|
75
|
+
if (index === -1)
|
|
76
|
+
return undefined;
|
|
77
|
+
return this.extractAt(index);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Extract an element by its key (if extractKey was provided)
|
|
81
|
+
* O(log n) time complexity
|
|
82
|
+
*/
|
|
83
|
+
extractByKey(key) {
|
|
84
|
+
if (!this.keyMap || !this.extractKey) {
|
|
85
|
+
throw new Error('extractKey function must be provided to use key-based extraction');
|
|
86
|
+
}
|
|
87
|
+
const index = this.keyMap.get(key);
|
|
88
|
+
if (index === undefined)
|
|
89
|
+
return undefined;
|
|
90
|
+
return this.extractAt(index);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if a key exists in the heap
|
|
94
|
+
* O(1) time complexity
|
|
95
|
+
*/
|
|
96
|
+
hasKey(key) {
|
|
97
|
+
if (!this.keyMap)
|
|
98
|
+
return false;
|
|
99
|
+
return this.keyMap.has(key);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get all elements as an array (does not modify heap)
|
|
103
|
+
* O(n) time complexity
|
|
104
|
+
*/
|
|
105
|
+
toArray() {
|
|
106
|
+
return [...this.heap];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Clear the heap
|
|
110
|
+
*/
|
|
111
|
+
clear() {
|
|
112
|
+
this.heap = [];
|
|
113
|
+
if (this.keyMap) {
|
|
114
|
+
this.keyMap.clear();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Extract element at specific index
|
|
119
|
+
*/
|
|
120
|
+
extractAt(index) {
|
|
121
|
+
const item = this.heap[index];
|
|
122
|
+
if (this.keyMap && this.extractKey) {
|
|
123
|
+
this.keyMap.delete(this.extractKey(item));
|
|
124
|
+
}
|
|
125
|
+
if (index === this.heap.length - 1) {
|
|
126
|
+
this.heap.pop();
|
|
127
|
+
return item;
|
|
128
|
+
}
|
|
129
|
+
const lastItem = this.heap.pop();
|
|
130
|
+
this.heap[index] = lastItem;
|
|
131
|
+
if (this.keyMap && this.extractKey) {
|
|
132
|
+
this.keyMap.set(this.extractKey(lastItem), index);
|
|
133
|
+
}
|
|
134
|
+
// Try bubbling up first
|
|
135
|
+
const parentIndex = Math.floor((index - 1) / 2);
|
|
136
|
+
if (parentIndex >= 0 && this.compareFn(this.heap[index], this.heap[parentIndex]) < 0) {
|
|
137
|
+
this.bubbleUp(index);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
this.bubbleDown(index);
|
|
141
|
+
}
|
|
142
|
+
return item;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Bubble up element at given index to maintain heap property
|
|
146
|
+
*/
|
|
147
|
+
bubbleUp(index) {
|
|
148
|
+
while (index > 0) {
|
|
149
|
+
const parentIndex = Math.floor((index - 1) / 2);
|
|
150
|
+
if (this.compareFn(this.heap[index], this.heap[parentIndex]) >= 0) {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
this.swap(index, parentIndex);
|
|
154
|
+
index = parentIndex;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Bubble down element at given index to maintain heap property
|
|
159
|
+
*/
|
|
160
|
+
bubbleDown(index) {
|
|
161
|
+
const length = this.heap.length;
|
|
162
|
+
while (true) {
|
|
163
|
+
const leftChild = 2 * index + 1;
|
|
164
|
+
const rightChild = 2 * index + 2;
|
|
165
|
+
let smallest = index;
|
|
166
|
+
if (leftChild < length &&
|
|
167
|
+
this.compareFn(this.heap[leftChild], this.heap[smallest]) < 0) {
|
|
168
|
+
smallest = leftChild;
|
|
169
|
+
}
|
|
170
|
+
if (rightChild < length &&
|
|
171
|
+
this.compareFn(this.heap[rightChild], this.heap[smallest]) < 0) {
|
|
172
|
+
smallest = rightChild;
|
|
173
|
+
}
|
|
174
|
+
if (smallest === index)
|
|
175
|
+
break;
|
|
176
|
+
this.swap(index, smallest);
|
|
177
|
+
index = smallest;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Swap two elements in the heap
|
|
182
|
+
*/
|
|
183
|
+
swap(i, j) {
|
|
184
|
+
const temp = this.heap[i];
|
|
185
|
+
this.heap[i] = this.heap[j];
|
|
186
|
+
this.heap[j] = temp;
|
|
187
|
+
if (this.keyMap && this.extractKey) {
|
|
188
|
+
this.keyMap.set(this.extractKey(this.heap[i]), i);
|
|
189
|
+
this.keyMap.set(this.extractKey(this.heap[j]), j);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluYXJ5LWhlYXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3V0aWxzL2JpbmFyeS1oZWFwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBSXJCLFlBQ1UsU0FBaUMsRUFDakMsVUFBZ0M7UUFEaEMsY0FBUyxHQUFULFNBQVMsQ0FBd0I7UUFDakMsZUFBVSxHQUFWLFVBQVUsQ0FBc0I7UUFMbEMsU0FBSSxHQUFRLEVBQUUsQ0FBQztRQU9yQixJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFXLElBQUk7UUFDYixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQzFCLENBQUM7SUFFRDs7T0FFRztJQUNJLE9BQU87UUFDWixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxJQUFJO1FBQ1QsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7O09BR0c7SUFDSSxNQUFNLENBQUMsSUFBTztRQUNuQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyQixJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ25DLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxD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
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { LifecycleComponent } from './lifecycle-component.js';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for pooled connection
|
|
4
|
+
*/
|
|
5
|
+
export interface IPooledConnection<T> {
|
|
6
|
+
id: string;
|
|
7
|
+
connection: T;
|
|
8
|
+
createdAt: number;
|
|
9
|
+
lastUsedAt: number;
|
|
10
|
+
useCount: number;
|
|
11
|
+
inUse: boolean;
|
|
12
|
+
metadata?: any;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Configuration options for the connection pool
|
|
16
|
+
*/
|
|
17
|
+
export interface IConnectionPoolOptions<T> {
|
|
18
|
+
minSize?: number;
|
|
19
|
+
maxSize?: number;
|
|
20
|
+
acquireTimeout?: number;
|
|
21
|
+
idleTimeout?: number;
|
|
22
|
+
maxUseCount?: number;
|
|
23
|
+
validateOnAcquire?: boolean;
|
|
24
|
+
validateOnReturn?: boolean;
|
|
25
|
+
queueTimeout?: number;
|
|
26
|
+
connectionFactory: () => Promise<T>;
|
|
27
|
+
connectionValidator?: (connection: T) => Promise<boolean>;
|
|
28
|
+
connectionDestroyer?: (connection: T) => Promise<void>;
|
|
29
|
+
onConnectionError?: (error: Error, connection?: T) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Enhanced connection pool with priority queue, backpressure, and lifecycle management
|
|
33
|
+
*/
|
|
34
|
+
export declare class EnhancedConnectionPool<T> extends LifecycleComponent {
|
|
35
|
+
private readonly options;
|
|
36
|
+
private readonly availableConnections;
|
|
37
|
+
private readonly activeConnections;
|
|
38
|
+
private readonly waitQueue;
|
|
39
|
+
private readonly mutex;
|
|
40
|
+
private readonly eventEmitter;
|
|
41
|
+
private connectionIdCounter;
|
|
42
|
+
private requestIdCounter;
|
|
43
|
+
private isClosing;
|
|
44
|
+
private metrics;
|
|
45
|
+
constructor(options: IConnectionPoolOptions<T>);
|
|
46
|
+
/**
|
|
47
|
+
* Initialize minimum number of connections
|
|
48
|
+
*/
|
|
49
|
+
private initializeMinConnections;
|
|
50
|
+
/**
|
|
51
|
+
* Start maintenance timer for idle connection cleanup
|
|
52
|
+
*/
|
|
53
|
+
private startMaintenance;
|
|
54
|
+
/**
|
|
55
|
+
* Perform maintenance tasks
|
|
56
|
+
*/
|
|
57
|
+
private performMaintenance;
|
|
58
|
+
/**
|
|
59
|
+
* Acquire a connection from the pool
|
|
60
|
+
*/
|
|
61
|
+
acquire(priority?: number, timeout?: number): Promise<IPooledConnection<T>>;
|
|
62
|
+
/**
|
|
63
|
+
* Try to acquire an available connection
|
|
64
|
+
*/
|
|
65
|
+
private tryAcquireConnection;
|
|
66
|
+
/**
|
|
67
|
+
* Checkout a connection for use
|
|
68
|
+
*/
|
|
69
|
+
private checkoutConnection;
|
|
70
|
+
/**
|
|
71
|
+
* Queue an acquire request
|
|
72
|
+
*/
|
|
73
|
+
private queueAcquireRequest;
|
|
74
|
+
/**
|
|
75
|
+
* Release a connection back to the pool
|
|
76
|
+
*/
|
|
77
|
+
release(connection: IPooledConnection<T>): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Create a new connection
|
|
80
|
+
*/
|
|
81
|
+
private createConnection;
|
|
82
|
+
/**
|
|
83
|
+
* Destroy a connection
|
|
84
|
+
*/
|
|
85
|
+
private destroyConnection;
|
|
86
|
+
/**
|
|
87
|
+
* Get current pool statistics
|
|
88
|
+
*/
|
|
89
|
+
getStats(): {
|
|
90
|
+
connectionsCreated: number;
|
|
91
|
+
connectionsDestroyed: number;
|
|
92
|
+
connectionsAcquired: number;
|
|
93
|
+
connectionsReleased: number;
|
|
94
|
+
acquireTimeouts: number;
|
|
95
|
+
validationFailures: number;
|
|
96
|
+
queueHighWaterMark: number;
|
|
97
|
+
available: number;
|
|
98
|
+
active: number;
|
|
99
|
+
waiting: number;
|
|
100
|
+
total: number;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Subscribe to pool events
|
|
104
|
+
*/
|
|
105
|
+
on(event: string, listener: Function): void;
|
|
106
|
+
/**
|
|
107
|
+
* Close the pool and cleanup resources
|
|
108
|
+
*/
|
|
109
|
+
protected onCleanup(): Promise<void>;
|
|
110
|
+
}
|