@dbs-portal/core-api
Version:
HTTP client and API utilities for DBS Portal
193 lines • 5.75 kB
JavaScript
/**
* Retry strategies for different scenarios
*/
/**
* Exponential backoff strategy
*/
export function exponentialBackoff(baseDelay = 1000, maxDelay = 30000, multiplier = 2) {
return (retryCount) => {
return Math.min(baseDelay * Math.pow(multiplier, retryCount), maxDelay);
};
}
/**
* Linear backoff strategy
*/
export function linearBackoff(baseDelay = 1000, increment = 1000) {
return (retryCount) => {
return baseDelay + increment * retryCount;
};
}
/**
* Fixed delay strategy
*/
export function fixedDelay(delay = 1000) {
return () => delay;
}
/**
* Jittered exponential backoff to avoid thundering herd
*/
export function jitteredExponentialBackoff(baseDelay = 1000, maxDelay = 30000, jitterFactor = 0.1) {
return (retryCount) => {
const exponentialDelay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay);
const jitter = exponentialDelay * jitterFactor * Math.random();
return exponentialDelay + jitter;
};
}
/**
* Retry condition for network errors only
*/
export function networkErrorsOnly(error) {
return !error.response; // No response means network error
}
/**
* Retry condition for server errors only
*/
export function serverErrorsOnly(error) {
const status = error.response?.status;
return status ? status >= 500 && status < 600 : false;
}
/**
* Retry condition for specific status codes
*/
export function statusCodesOnly(codes) {
return (error) => {
const status = error.response?.status;
return status ? codes.includes(status) : false;
};
}
/**
* Retry condition for timeout errors
*/
export function timeoutErrorsOnly(error) {
return error.code === 'TIMEOUT' || error.message.includes('timeout');
}
/**
* Retry condition that respects Retry-After headers
*/
export function respectRetryAfter(error) {
if (error.response?.status === 429) {
// Rate limited - check if Retry-After header is present
const retryAfter = error.response.headers?.['retry-after'] || error.response.headers?.['Retry-After'];
return !!retryAfter;
}
// Default retry logic for other errors
return !error.response || (error.response.status >= 500 && error.response.status < 600);
}
/**
* Comprehensive retry condition for production use
*/
export function productionRetryCondition(error) {
// Don't retry client errors (4xx) except for specific cases
if (error.response) {
const status = error.response.status;
// Retry on server errors
if (status >= 500 && status < 600) {
return true;
}
// Retry on specific client errors
if (status === 408 || status === 429) {
return true;
}
// Don't retry other client errors
return false;
}
// Retry network errors
return true;
}
/**
* Conservative retry condition for critical operations
*/
export function conservativeRetryCondition(error) {
// Only retry on clear network errors and 503 Service Unavailable
if (!error.response) {
return true; // Network error
}
return error.response.status === 503;
}
/**
* Aggressive retry condition for non-critical operations
*/
export function aggressiveRetryCondition(error) {
if (!error.response) {
return true; // Network error
}
const status = error.response.status;
// Don't retry on authentication/authorization errors
if (status === 401 || status === 403) {
return false;
}
// Don't retry on not found
if (status === 404) {
return false;
}
// Don't retry on bad request
if (status === 400) {
return false;
}
// Retry everything else
return true;
}
/**
* Creates a retry strategy that respects Retry-After headers
*/
export function createRetryAfterStrategy() {
return {
retries: 3,
retryCondition: respectRetryAfter,
retryDelay: (retryCount) => {
// For now, just use exponential backoff
// In a real implementation, you'd pass the error to access headers
// Fallback to exponential backoff
return exponentialBackoff()(retryCount);
},
};
}
/**
* Creates a retry strategy for API rate limiting
*/
export function createRateLimitStrategy() {
return {
retries: 5,
retryCondition: (error) => error.response?.status === 429,
retryDelay: (retryCount) => {
// For now, just use exponential backoff with jitter
// In a real implementation, you'd pass the error to access headers
// Fallback to exponential backoff with jitter
return jitteredExponentialBackoff(2000, 60000)(retryCount);
},
};
}
/**
* Creates a retry strategy for unreliable networks
*/
export function createUnreliableNetworkStrategy() {
return {
retries: 5,
retryCondition: (error) => {
// Retry on network errors and server errors
return !error.response || (error.response.status >= 500 && error.response.status < 600);
},
retryDelay: jitteredExponentialBackoff(500, 10000, 0.2),
};
}
/**
* Creates a retry strategy for critical operations
*/
export function createCriticalOperationStrategy() {
return {
retries: 2,
retryCondition: conservativeRetryCondition,
retryDelay: fixedDelay(1000),
};
}
/**
* Creates a retry strategy for background operations
*/
export function createBackgroundOperationStrategy() {
return {
retries: 10,
retryCondition: aggressiveRetryCondition,
retryDelay: exponentialBackoff(1000, 300000), // Up to 5 minutes
};
}
//# sourceMappingURL=retry-strategies.js.map