Async Pipelines

Powerful Asynchronous Programming with BoxFuture Pipelines

Introduced in v1.4.0

What Are Async Pipelines?

Async pipelines in BoxLang are powerful chains of asynchronous operations that allow you to compose complex workflows from simple, reusable components. Built on top of BoxFuture (which extends Java's CompletableFuture), they provide a fluent, functional programming approach to handling asynchronous operations.

Input → Transform → Process → Combine → Result
  📥      ⚡️        🔄        🔗       ✅

Think of pipelines as assembly lines for data processing - each stage performs a specific operation and passes the result to the next stage, all running asynchronously for maximum performance.

💡 Why Use Async Pipelines?

  • 🔄 Non-blocking: Operations don't freeze your application

  • ⚡ Performance: Parallel execution and optimized resource usage

  • 🧩 Composability: Chain operations in a readable, maintainable way

  • 🎯 Error Handling: Centralized exception management and recovery

  • 🔀 Flexibility: Mix synchronous and asynchronous operations seamlessly

  • 📊 Monitoring: Built-in logging and performance tracking

🎯 Entry Points: Creating BoxFutures

BoxLang provides two main entry points for creating async pipelines:

🆕 futureNew() BIF

The primary way to create BoxFuture instances with maximum flexibility:

asyncRun() BIF

Simplified function for running code asynchronously:

🎨 BoxFuture Pipeline Methods

BoxFuture extends CompletableFuture with BoxLang-specific enhancements and fluent methods:

🔄 Transformation Methods

Method
Purpose
Returns
Usage

then( function )

Transform result synchronously

BoxFuture

future.then( x => x * 2 )

thenAsync( function )

Transform result asynchronously

BoxFuture

future.thenAsync( x => processAsync(x) )

then( function, executor )

Transform with specific executor

BoxFuture

future.then( x => x + 1, "cpu-tasks" )

thenAsync( function, executor )

Transform async with executor

BoxFuture

future.thenAsync( transform, "io-tasks" )

🚨 Error Handling Methods

Method
Purpose
Returns
Usage

onError( function )

Handle exceptions

BoxFuture

future.onError( ex => handleError(ex) )

exceptionally( function )

Handle exceptions (Java style)

BoxFuture

future.exceptionally( ex => defaultValue )

⏰ Timeout Methods

Method
Purpose
Returns
Usage

orTimeout( timeout )

Timeout in milliseconds

BoxFuture

future.orTimeout( 5000 )

orTimeout( timeout, unit )

Timeout with time unit

BoxFuture

future.orTimeout( 5, "seconds" )

completeOnTimeout( value, timeout )

Complete with value on timeout (ms)

BoxFuture

future.completeOnTimeout( "default", 3000 )

completeOnTimeout( value, timeout, unit )

Complete with value on timeout

BoxFuture

future.completeOnTimeout( null, 1, "minute" )

📥 Result Retrieval Methods

Method
Purpose
Returns
Usage

get()

Get result (blocking)

Object

result = future.get()

get( timeout )

Get result with timeout (ms)

Object

result = future.get( 5000 )

get( timeout, unit )

Get result with timeout

Object

result = future.get( 30, "seconds" )

getOrDefault( defaultValue )

Get result or default

Object

result = future.getOrDefault( "fallback" )

join()

Get result (blocking, unchecked)

Object

result = future.join()

joinOrDefault( defaultValue )

Join with default value

Object

result = future.joinOrDefault( 0 )

getAsAttempt()

Get result as Attempt object

Attempt

attempt = future.getAsAttempt()

getAsAttempt( timeout )

Get as Attempt with timeout (ms)

Attempt

attempt = future.getAsAttempt( 5000 )

getAsAttempt( timeout, unit )

Get as Attempt with timeout

Attempt

attempt = future.getAsAttempt( 1, "minute" )

🌊 Pipeline Examples

Basic Pipeline

Complex Data Processing Pipeline

Parallel Processing with all()

Error Recovery Pipeline

🔗 Combining Futures

Sequential Chaining

Parallel Execution

🎯 Advanced Patterns

🔄 Retry Pattern

🔀 Fan-out/Fan-in Pattern

🚪 Circuit Breaker Pattern

🔧 Executor Integration

Using Specific Executors

Dynamic Executor Selection

📊 Monitoring and Debugging

Performance Tracking

Debug Pipeline

🌟 Static Factory Methods

BoxFuture provides convenient static methods for common scenarios:

Creating Futures

Delayed Execution

🚨 Error Handling Best Practices

1. Always Handle Errors

2. Use Timeouts

3. Graceful Degradation

🎯 Performance Tips

1. Choose the Right Executor

2. Avoid Blocking Operations

3. Use Parallel Processing

🔍 Common Patterns and Use Cases

API Orchestration

Data Pipeline Processing

Real-time Processing

🔚 Conclusion

BoxFuture async pipelines provide a powerful, flexible way to handle asynchronous operations in BoxLang. By combining the fluent API with proper error handling, timeouts, and executor selection, you can build robust, high-performance applications that scale effectively.

Key takeaways:

  • Use futureNew() and asyncRun() as your primary entry points

  • Chain operations with then() and thenAsync() for readable pipelines

  • Always include error handling with onError() and exceptionally()

  • Use timeouts to prevent hanging operations

  • Choose appropriate executors for different types of work

  • Leverage parallel processing with BoxFuture.all() for performance

Start simple with basic transformations, then gradually incorporate more advanced patterns as your needs grow. The async pipeline approach will help you build more responsive, efficient applications that can handle complex asynchronous workflows with ease.

Last updated

Was this helpful?