async def process_with_retry(
        func, 
        item, 
        max_retries=3, 
        initial_backoff=1.0, 
        backoff_factor=2.0, 
        jitter=0.1,
        timeout=None,
        on_success=None,
        on_failure=None,
        logger=None
    ):
        """Process a single item with retry logic and backoff."""
        logger = logger or logging.getLogger(__name__)
        attempts = 0
        last_exception = None

        while attempts <= max_retries:
            try:
                # Add timeout if specified
                if timeout is not None:
                    result = await asyncio.wait_for(func(item), timeout=timeout)
                else:
                    result = await func(item)

                # Call success callback if provided
                if on_success:
                    on_success(item, result)

                return item, result, None

            except Exception as e:
                attempts += 1
                last_exception = e

                if attempts <= max_retries:
                    # Calculate backoff time with jitter
                    backoff_time = initial_backoff * (backoff_factor ** (attempts - 1))
                    jitter_amount = backoff_time * jitter
                    actual_backoff = backoff_time + random.uniform(-jitter_amount, jitter_amount)
                    actual_backoff = max(0.1, actual_backoff)  # Ensure minimum backoff

                    logger.warning(
                        f"Attempt {attempts}/{max_retries} failed for item {item}. "
                        f"Retrying in {actual_backoff:.2f}s. Error: {str(e)}"
                    )

                    await asyncio.sleep(actual_backoff)
                else:
                    if on_failure:
                        on_failure(item, last_exception)

                    logger.error(
                        f"All {max_retries} retry attempts failed for item {item}. "
                        f"Final error: {str(last_exception)}"
                    )

        return item, None, last_exception
Process a single item with retry logic and backoff.
app.py