Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,33 @@ $pipeline->branch(

## πŸ“š Advanced Usage

### Laravel Pipeline Integration

Use Laravel's Pipeline within Sentinels workflows for the best of both worlds:

```php
use Vampires\Sentinels\Facades\Sentinels;

// Mix Laravel pipes with Sentinels agents
$result = Sentinels::pipeline()
->pipe(new ValidateOrderAgent()) // Sentinels agent
->pipe(Sentinels::laravelPipeline([ // Laravel pipes
'uppercase_name',
'format_email',
function ($data, $next) {
$data['processed_at'] = now();
return $next($data);
}
]))
->pipe(new AuditLogAgent()) // Back to Sentinels
->through($orderData);

// All Sentinels features (correlation, error handling, events) work seamlessly
echo $result->correlationId; // Full traceability preserved
```

**πŸ“– [See complete Laravel Pipeline integration examples β†’](docs/laravel-pipeline-integration-examples.md)**

### Dynamic Routing

Route contexts to different agents based on content:
Expand Down Expand Up @@ -716,6 +743,16 @@ php artisan sentinels:list --stats

## πŸ”„ When to Use Sentinels vs Alternatives

### "Doesn't Laravel already do this pipeline thing?"

**Great question!** Laravel does include a Pipeline class, and it's excellent for many use cases. Sentinels and Laravel Pipeline solve different problems:

- **Laravel Pipeline**: Perfect for simple data transformations and middleware-style processing
- **Sentinels Pipeline**: Designed for complex business workflows with observability and error recovery

**πŸ“– [Quick summary and decision guide β†’](docs/laravel-pipeline-summary.md)**
**πŸ“– [Complete comparison and integration guide β†’](docs/laravel-pipeline-comparison.md)**

### Feature Comparison Matrix

| Feature | Laravel Pipeline | Job Chains | Events/Listeners | **Sentinels** |
Expand Down Expand Up @@ -945,6 +982,19 @@ Sentinels::pipeline()

**Sentinels is Laravel for workflows** - bringing the same joy, productivity, and elegance to complex processing that Laravel brings to web development.

## πŸ“š Complete Documentation

- **[Getting Started](docs/getting-started.md)** - Your first Sentinels pipeline
- **[Laravel Pipeline Summary](docs/laravel-pipeline-summary.md)** - Quick answer to "doesn't Laravel already do this?"
- **[Laravel Pipeline Comparison](docs/laravel-pipeline-comparison.md)** - When to use Laravel Pipeline vs Sentinels
- **[Laravel Pipeline Integration](docs/laravel-pipeline-integration-examples.md)** - Using both together
- **[Pipelines Deep Dive](docs/pipelines.md)** - Advanced pipeline patterns
- **[Agent Development](docs/agents.md)** - Building powerful agents
- **[Context Management](docs/context.md)** - Working with immutable context
- **[Error Handling](docs/error-handling.md)** - Robust error recovery
- **[Testing Guide](docs/testing.md)** - Testing your workflows
- **[API Reference](docs/api-reference.md)** - Complete API documentation

## 🀝 Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
Expand Down
309 changes: 309 additions & 0 deletions docs/laravel-pipeline-comparison.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
# Laravel Pipeline vs Sentinels: When to Use Which?

## "Doesn't Laravel already do this pipeline thing?"

Great question! Laravel does include a Pipeline class, and it's excellent for many use cases. However, Sentinels addresses different needs. Here's when to use each:

## Quick Decision Guide

### Use **Laravel's Pipeline** when you need:
- βœ… Simple data transformations or filtering
- βœ… Middleware-style processing
- βœ… Lightweight, minimal overhead
- βœ… Working with any data types
- βœ… Basic sequential processing

### Use **Sentinels Pipeline** when you need:
- βœ… Complex business workflows with multiple steps
- βœ… Parallel or asynchronous execution
- βœ… Rich error handling and retry policies
- βœ… Observability (logging, tracing, correlation IDs)
- βœ… Conditional branching and routing
- βœ… Agent-based architecture for team development

## Side-by-Side Comparison

| Feature | Laravel Pipeline | Sentinels Pipeline |
|---------|------------------|-------------------|
| **Complexity** | Simple, lightweight | Feature-rich, comprehensive |
| **Learning Curve** | Minimal | Moderate |
| **Performance** | Fast, minimal overhead | Good, with observability overhead |
| **Async Support** | ❌ | βœ… True parallel execution |
| **Error Handling** | Basic exceptions | βœ… Retry policies, recovery |
| **Observability** | ❌ | βœ… Events, metrics, correlation |
| **Conditional Logic** | ❌ | βœ… Branching, routing |
| **Testing** | Standard PHPUnit | βœ… Built-in test helpers |
| **Team Development** | Single developer friendly | βœ… Multi-developer workflows |

## Code Examples

### Laravel Pipeline - Perfect for Simple Transformations

```php
use Illuminate\Pipeline\Pipeline;

// Simple data processing
$result = app(Pipeline::class)
->send($user)
->through([
function ($user, $next) {
$user->name = strtoupper($user->name);
return $next($user);
},
function ($user, $next) {
$user->email = strtolower($user->email);
return $next($user);
},
])
->thenReturn();
```

### Sentinels Pipeline - Complex Business Workflows

```php
use Vampires\Sentinels\Facades\Sentinels;

// Complex order processing with error handling and observability
$result = Sentinels::pipeline()
->pipe(new ValidateOrderAgent())
->pipe(new CheckInventoryAgent())
->pipe(new ProcessPaymentAgent())
->branch(
fn($ctx) => $ctx->hasTag('premium'),
$premiumPipeline,
$standardPipeline
)
->onError(function ($context, $exception) {
// Sophisticated error recovery
return $context->addError("Order failed: " . $exception->getMessage());
})
->through($order);

// Every step is logged with correlation IDs for debugging
// Automatic retry policies for transient failures
// Rich context preserved throughout execution
```

## Migration Strategies

### 1. Start Simple, Scale Complex

```php
// Begin with Laravel Pipeline for simple cases
$basicResult = app(Pipeline::class)
->send($data)
->through($simpleTransformations)
->thenReturn();

// Migrate to Sentinels when complexity grows
$complexResult = Sentinels::pipeline()
->pipe(new BusinessLogicAgent())
->mode('parallel')
->async()
->through($data);
```

### 2. Use Both in the Same Project

```php
// Laravel Pipeline for simple utilities
class UserFormatter
{
public function format($user)
{
return app(Pipeline::class)
->send($user)
->through([FormatName::class, FormatEmail::class])
->thenReturn();
}
}

// Sentinels for complex business processes
class OrderProcessor
{
public function process($order)
{
return Sentinels::pipeline()
->pipe(new ValidateOrderAgent())
->pipe(new ProcessPaymentAgent())
->through($order);
}
}
```

## When Each Pattern Shines

### Laravel Pipeline: The Swiss Army Knife

```php
// Perfect for:
// - HTTP middleware
// - Data validation chains
// - Simple transformations
// - Request/response processing

$request = app(Pipeline::class)
->send($request)
->through([
AuthMiddleware::class,
ValidationMiddleware::class,
RateLimitMiddleware::class,
])
->then(function ($request) {
return $this->handleRequest($request);
});
```

### Sentinels: The Orchestra Conductor

```php
// Perfect for:
// - Multi-step business processes
// - Background job orchestration
// - API integrations with retry logic
// - Complex workflows with branching

$result = Sentinels::pipeline()
->pipe(new ExtractDataAgent())
->pipe(new TransformDataAgent())
->mode('parallel')
->async()
->pipe(new SaveToDbAgent())
->pipe(new SendNotificationAgent())
->pipe(new UpdateAnalyticsAgent())
->onError(new RetryWithBackoffPolicy())
->through($importData);
```

## Interoperability

### Using Laravel Pipeline within Sentinels Agents

```php
class DataTransformationAgent extends BaseAgent
{
protected function handle(Context $context): Context
{
// Use Laravel Pipeline for data transformation within an agent
$transformedData = app(Pipeline::class)
->send($context->payload)
->through([
new NormalizeFormat(),
new ValidateFields(),
new EnrichData(),
])
->thenReturn();

return $context->with($transformedData);
}
}
```

### Converting Laravel Pipeline to Sentinels

```php
// Create an agent that wraps Laravel Pipeline behavior
class LaravelPipelineAgent extends BaseAgent
{
public function __construct(
protected array $pipes,
protected string $method = 'handle'
) {}

protected function handle(Context $context): Context
{
$result = app(Pipeline::class)
->send($context->payload)
->through($this->pipes)
->via($this->method)
->thenReturn();

return $context->with($result);
}
}

// Use it in Sentinels pipelines
$result = Sentinels::pipeline()
->pipe(new LaravelPipelineAgent([
FormatDataPipe::class,
ValidateDataPipe::class,
]))
->pipe(new ComplexBusinessAgent())
->through($data);
```

## Best Practices

### 1. Choose Based on Complexity

```php
// Simple? Laravel Pipeline
if ($isSimpleTransformation) {
return app(Pipeline::class)->send($data)->through($pipes)->thenReturn();
}

// Complex? Sentinels Pipeline
return Sentinels::pipeline()
->pipe($agents)
->mode('parallel')
->onError($errorHandler)
->through($data);
```

### 2. Progressive Enhancement

```php
// Start with Laravel Pipeline
class DataProcessor
{
public function process($data)
{
return app(Pipeline::class)
->send($data)
->through($this->getTransformations())
->thenReturn();
}
}

// Enhance to Sentinels when needed
class EnhancedDataProcessor
{
public function process($data)
{
return Sentinels::pipeline()
->pipe(new ValidationAgent())
->pipe(new LaravelPipelineAgent($this->getTransformations()))
->pipe(new AuditAgent())
->through($data);
}
}
```

### 3. Team Guidelines

```php
// Establish clear patterns in your team:

// For HTTP middleware and request processing
use Illuminate\Pipeline\Pipeline;

// For background jobs and business workflows
use Vampires\Sentinels\Facades\Sentinels;

// For simple data transformations
use Illuminate\Pipeline\Pipeline;

// For complex processes requiring observability
use Vampires\Sentinels\Facades\Sentinels;
```

## Conclusion

Laravel's Pipeline and Sentinels Pipeline serve different purposes:

- **Laravel Pipeline**: Simple, fast, perfect for middleware and basic transformations
- **Sentinels Pipeline**: Complex workflows, observability, error recovery, team collaboration

Both are excellent tools. Choose based on your specific needs, and don't hesitate to use both in the same application for different purposes.

The key is matching the tool to the job complexity and requirements.
Loading