@push.rocks/smartproxy
Version:
A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.
216 lines • 13.2 kB
JavaScript
/**
* Async utility functions for SmartProxy
* Provides non-blocking alternatives to synchronous operations
*/
/**
* Delays execution for the specified number of milliseconds
* Non-blocking alternative to busy wait loops
* @param ms - Number of milliseconds to delay
* @returns Promise that resolves after the delay
*/
export async function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Retry an async operation with exponential backoff
* @param fn - The async function to retry
* @param options - Retry options
* @returns The result of the function or throws the last error
*/
export async function retryWithBackoff(fn, options = {}) {
const { maxAttempts = 3, initialDelay = 100, maxDelay = 10000, factor = 2, onRetry } = options;
let lastError = null;
let currentDelay = initialDelay;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
}
catch (error) {
lastError = error;
if (attempt === maxAttempts) {
throw error;
}
if (onRetry) {
onRetry(attempt, error);
}
await delay(currentDelay);
currentDelay = Math.min(currentDelay * factor, maxDelay);
}
}
throw lastError || new Error('Retry failed');
}
/**
* Execute an async operation with a timeout
* @param fn - The async function to execute
* @param timeoutMs - Timeout in milliseconds
* @param timeoutError - Optional custom timeout error
* @returns The result of the function or throws timeout error
*/
export async function withTimeout(fn, timeoutMs, timeoutError) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(timeoutError || new Error(`Operation timed out after ${timeoutMs}ms`));
}, timeoutMs);
});
return Promise.race([fn(), timeoutPromise]);
}
/**
* Run multiple async operations in parallel with a concurrency limit
* @param items - Array of items to process
* @param fn - Async function to run for each item
* @param concurrency - Maximum number of concurrent operations
* @returns Array of results in the same order as input
*/
export async function parallelLimit(items, fn, concurrency) {
const results = new Array(items.length);
const executing = new Set();
for (let i = 0; i < items.length; i++) {
const promise = fn(items[i], i).then(result => {
results[i] = result;
executing.delete(promise);
});
executing.add(promise);
if (executing.size >= concurrency) {
await Promise.race(executing);
}
}
await Promise.all(executing);
return results;
}
/**
* Debounce an async function
* @param fn - The async function to debounce
* @param delayMs - Delay in milliseconds
* @returns Debounced function with cancel method
*/
export function debounceAsync(fn, delayMs) {
let timeoutId = null;
let lastPromise = null;
const debounced = ((...args) => {
if (timeoutId) {
clearTimeout(timeoutId);
}
lastPromise = new Promise((resolve, reject) => {
timeoutId = setTimeout(async () => {
timeoutId = null;
try {
const result = await fn(...args);
resolve(result);
}
catch (error) {
reject(error);
}
}, delayMs);
});
return lastPromise;
});
debounced.cancel = () => {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
};
return debounced;
}
/**
* Create a mutex for ensuring exclusive access to a resource
*/
export class AsyncMutex {
constructor() {
this.queue = [];
this.locked = false;
}
async acquire() {
if (!this.locked) {
this.locked = true;
return () => this.release();
}
return new Promise(resolve => {
this.queue.push(() => {
resolve(() => this.release());
});
});
}
release() {
const next = this.queue.shift();
if (next) {
next();
}
else {
this.locked = false;
}
}
async runExclusive(fn) {
const release = await this.acquire();
try {
return await fn();
}
finally {
release();
}
}
}
/**
* Circuit breaker for protecting against cascading failures
*/
export class CircuitBreaker {
constructor(options) {
this.options = options;
this.failureCount = 0;
this.lastFailureTime = 0;
this.state = 'closed';
}
async execute(fn) {
if (this.state === 'open') {
if (Date.now() - this.lastFailureTime > this.options.resetTimeout) {
this.setState('half-open');
}
else {
throw new Error('Circuit breaker is open');
}
}
try {
const result = await fn();
this.onSuccess();
return result;
}
catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
if (this.state !== 'closed') {
this.setState('closed');
}
}
onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.options.failureThreshold) {
this.setState('open');
}
}
setState(state) {
if (this.state !== state) {
this.state = state;
if (this.options.onStateChange) {
this.options.onStateChange(state);
}
}
}
isOpen() {
return this.state === 'open';
}
getState() {
return this.state;
}
recordSuccess() {
this.onSuccess();
}
recordFailure() {
this.onFailure();
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3V0aWxzL2FzeW5jLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVIOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUNwQyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3pELENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZ0JBQWdCLENBQ3BDLEVBQW9CLEVBQ3BCLFVBTUksRUFBRTtJQUVOLE1BQU0sRUFDSixXQUFXLEdBQUcsQ0FBQyxFQUNmLFlBQVksR0FBRyxHQUFHLEVBQ2xCLFFBQVEsR0FBRyxLQUFLLEVBQ2hCLE1BQU0sR0FBRyxDQUFDLEVBQ1YsT0FBTyxFQUNSLEdBQUcsT0FBTyxDQUFDO0lBRVosSUFBSSxTQUFTLEdBQWlCLElBQUksQ0FBQztJQUNuQyxJQUFJLFlBQVksR0FBRyxZQUFZLENBQUM7SUFFaEMsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxJQUFJLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ3hELElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUNwQixDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixTQUFTLEdBQUcsS0FBSyxDQUFDO1lBRWxCLElBQUksT0FBTyxLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUM1QixNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFFRCxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLE9BQU8sQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDMUIsQ0FBQztZQUVELE1BQU0sS0FBSyxDQUFDLFlB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