'transient', 'retry_safe' => true, 'message' => 'Transient error detected - will retry with exponential backoff', ); } } // Check for permanent patterns. foreach ( self::PERMANENT_ERROR_PATTERNS as $pattern ) { if ( strpos( $error_lower, $pattern ) !== false ) { return array( 'type' => 'permanent', 'retry_safe' => false, 'message' => 'Permanent error - manual intervention required', ); } } // Unknown error - cautiously allow retry. return array( 'type' => 'unknown', 'retry_safe' => true, 'message' => 'Unknown error type - will retry cautiously', ); } /** * Calculate next retry delay with exponential backoff * * Retry schedule: * - Attempt 1: 5 seconds * - Attempt 2: 30 seconds * - Attempt 3: 5 minutes (300 seconds) * * @param int $attempt_number The attempt number (1-based). * @return int Delay in seconds before next retry. */ public static function calculate_retry_delay( $attempt_number ) { // Exponential backoff: 5s, 30s, 5min. $delays = array( 5, 30, 300 ); $index = min( $attempt_number - 1, count( $delays ) - 1 ); return $delays[ $index ]; } /** * Format retry schedule for display * * @param int $max_attempts Maximum number of retry attempts. * @return string Human-readable retry schedule. */ public static function get_retry_schedule_text( $max_attempts = 3 ) { $schedule_parts = array(); for ( $i = 1; $i <= $max_attempts; $i++ ) { $delay = self::calculate_retry_delay( $i ); $schedule_parts[] = sprintf( /* translators: 1: attempt number, 2: delay in seconds */ __( 'Attempt %1$d: %2$ds', 'gregius-data' ), $i, $delay ); } return implode( ', ', $schedule_parts ); } }