from fibonacci import Workflow
from fibonacci.exceptions import (
FibonacciError,
NodeExecutionError,
ToolError,
ValidationError,
AuthenticationError,
RateLimitError,
TimeoutError,
)
import time
import logging
logger = logging.getLogger(__name__)
def execute_with_handling(workflow, inputs, max_retries=3):
"""Execute workflow with comprehensive error handling."""
for attempt in range(max_retries):
try:
return workflow.execute(inputs=inputs)
except ValidationError as e:
# Input/output validation - don't retry, fix the data
logger.error(f"Validation error: {e.errors}")
raise
except AuthenticationError as e:
# Auth error - don't retry, fix credentials
logger.error(f"Authentication failed: {e.reason}")
raise
except RateLimitError as e:
# Rate limited - wait and retry
logger.warning(f"Rate limited, waiting {e.retry_after}s")
time.sleep(e.retry_after)
continue
except TimeoutError as e:
# Timeout - may retry with longer timeout
logger.warning(f"Timeout after {e.elapsed}s at node {e.node_id}")
if attempt < max_retries - 1:
continue
raise
except NodeExecutionError as e:
# Node failed - log details, maybe use partial results
logger.error(f"Node {e.node_id} failed: {e.message}")
if e.partial_results:
logger.info(f"Partial results available: {list(e.partial_results.keys())}")
raise
except ToolError as e:
# Tool error - may retry for transient issues
logger.error(f"Tool {e.tool_name} failed: {e.message}")
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
continue
raise
except FibonacciError as e:
# Catch-all for other Fibonacci errors
logger.error(f"Fibonacci error: {e.message}")
raise
raise RuntimeError(f"Failed after {max_retries} attempts")