Add DNS retry logic to Drift initialization

- Handles transient network failures (EAI_AGAIN, ENOTFOUND, ETIMEDOUT)
- Automatically retries up to 3 times with 2s delay between attempts
- Logs retry attempts for monitoring
- Prevents 500 errors from temporary DNS hiccups
- Fixes: n8n workflow failures during brief network issues

Impact:
- Improves reliability during DNS/network instability
- Reduces false negatives (missed trades due to transient errors)
- User-friendly retry logs for diagnostics
This commit is contained in:
mindesbunister
2025-11-13 16:05:42 +01:00
parent bd9633fbc2
commit 5e826dee5d

View File

@@ -75,8 +75,52 @@ export class DriftService {
console.log('✅ Drift service created for wallet:', this.wallet.publicKey.toString())
}
/**
* Retry helper for handling transient network failures (DNS, timeouts)
*/
private async retryOperation<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
delayMs: number = 2000,
operationName: string = 'operation'
): Promise<T> {
let lastError: Error | null = null
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation()
} catch (error: any) {
lastError = error
// Check if it's a transient network error
const isTransient =
error?.message?.includes('fetch failed') ||
error?.message?.includes('EAI_AGAIN') ||
error?.message?.includes('ENOTFOUND') ||
error?.message?.includes('ETIMEDOUT') ||
error?.message?.includes('ECONNREFUSED') ||
error?.code === 'EAI_AGAIN' ||
error?.cause?.code === 'EAI_AGAIN'
if (!isTransient || attempt === maxRetries) {
// Non-transient error or max retries reached - fail immediately
throw error
}
console.log(`⚠️ ${operationName} failed (attempt ${attempt}/${maxRetries}): ${error?.message || error}`)
console.log(`⏳ Retrying in ${delayMs}ms...`)
// Wait before retry
await new Promise(resolve => setTimeout(resolve, delayMs))
}
}
throw lastError || new Error(`${operationName} failed after ${maxRetries} retries`)
}
/**
* Initialize Drift client and subscribe to account updates
* Includes automatic retry for transient network failures (DNS, timeouts)
*/
async initialize(): Promise<void> {
if (this.isInitialized) {
@@ -87,6 +131,8 @@ export class DriftService {
try {
console.log('🚀 Initializing Drift Protocol client...')
// Wrap initialization in retry logic to handle DNS failures
await this.retryOperation(async () => {
// Initialize Drift SDK (gets program IDs and config)
const sdkConfig = initialize({
env: this.config.env === 'devnet' ? 'devnet' : 'mainnet-beta'
@@ -102,18 +148,19 @@ export class DriftService {
},
})
// Subscribe to Drift account updates
// Subscribe to Drift account updates (this makes RPC calls)
await this.driftClient.subscribe()
console.log('✅ Drift client subscribed to account updates')
// Get user account
this.user = this.driftClient.getUser()
}, 3, 2000, 'Drift initialization')
this.isInitialized = true
console.log('✅ Drift service initialized successfully')
} catch (error) {
console.error('❌ Failed to initialize Drift service:', error)
console.error('❌ Failed to initialize Drift service after retries:', error)
throw error
}
}