react-native-healthkit-bridge
Version:
A comprehensive React Native bridge for Apple HealthKit with TypeScript support, advanced authorization, and flexible data queries
98 lines (97 loc) • 3.56 kB
JavaScript
import { HEALTHKIT_CONFIG } from '../config/healthkit.config';
export class RetryManager {
constructor() {
this.defaultConfig = {
maxAttempts: HEALTHKIT_CONFIG.MAX_RETRIES,
baseDelay: HEALTHKIT_CONFIG.RETRY_DELAY,
maxDelay: 10000, // 10 seconds
backoffMultiplier: 2,
retryableErrors: [
'ERR_QUERY',
'ERR_NETWORK',
'ERR_TIMEOUT',
'ERR_HEALTHKIT_UNAVAILABLE'
]
};
}
static getInstance() {
if (!RetryManager.instance) {
RetryManager.instance = new RetryManager();
}
return RetryManager.instance;
}
async withRetry(operation, config) {
const finalConfig = Object.assign(Object.assign({}, this.defaultConfig), config);
const startTime = Date.now();
let lastError;
for (let attempt = 1; attempt <= finalConfig.maxAttempts; attempt++) {
try {
const data = await operation();
return {
success: true,
data,
attempts: attempt,
totalTime: Date.now() - startTime
};
}
catch (error) {
lastError = error;
// Check if error is retryable
if (!this.isRetryableError(error, finalConfig.retryableErrors)) {
return {
success: false,
error,
attempts: attempt,
totalTime: Date.now() - startTime
};
}
// If this is the last attempt, don't wait
if (attempt === finalConfig.maxAttempts) {
break;
}
// Calculate delay with exponential backoff
const delay = Math.min(finalConfig.baseDelay * Math.pow(finalConfig.backoffMultiplier, attempt - 1), finalConfig.maxDelay);
await this.sleep(delay);
}
}
return {
success: false,
error: lastError,
attempts: finalConfig.maxAttempts,
totalTime: Date.now() - startTime
};
}
isRetryableError(error, retryableErrors) {
if (!retryableErrors || retryableErrors.length === 0) {
return true; // Retry all errors by default
}
const errorCode = (error === null || error === void 0 ? void 0 : error.code) || (error === null || error === void 0 ? void 0 : error.message) || '';
return retryableErrors.some(retryableError => errorCode.includes(retryableError));
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Helper method for common retry scenarios
async retryQuery(operation) {
const result = await this.withRetry(operation, {
retryableErrors: ['ERR_QUERY', 'ERR_TIMEOUT']
});
if (!result.success) {
throw result.error;
}
return result.data;
}
async retryAuth(operation) {
const result = await this.withRetry(operation, {
retryableErrors: ['ERR_AUTHORIZATION', 'ERR_HEALTHKIT_UNAVAILABLE']
});
if (!result.success) {
throw result.error;
}
return result.data;
}
}
// Convenience function
export function withRetry(operation, config) {
return RetryManager.getInstance().withRetry(operation, config);
}