Files
michaelschiemer/docs/middleware-robustness.md
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

5.3 KiB

Middleware System Robustness Improvements

This document describes the improvements made to the middleware system to make it more robust and provides guidelines for developing robust middlewares.

Improvements Implemented

1. Exception Handling

The ExceptionHandlingMiddleware has been positioned as the first middleware in the chain to ensure it can catch exceptions from all other middlewares. This ensures that any exception thrown by a middleware will be properly handled and converted to an appropriate HTTP response.

2. Timeout Mechanism

A timeout mechanism has been added to the MiddlewareInvoker to prevent long-running middlewares from blocking requests indefinitely. If a middleware exceeds its configured timeout, a MiddlewareTimeoutException is thrown, which is then caught by the ExceptionHandlingMiddleware.

Timeouts can be configured:

  • Globally via the MIDDLEWARE_TIMEOUT environment variable (default: 5 seconds)
  • Per middleware class via the $middlewareTimeouts parameter in the MiddlewareInvoker constructor

3. Circuit Breaker Pattern

A circuit breaker pattern has been implemented to prevent repeatedly failing middlewares from being executed. The MiddlewareCircuitBreaker class uses the existing CircuitBreaker module to track middleware failures and temporarily disable middlewares that fail too often.

The circuit breaker has three states:

  • Closed: Normal operation, middleware is allowed to execute
  • Open: Too many failures, middleware is not allowed to execute
  • Half-Open: After a cooldown period, allows one execution to test if the middleware is working again

The integration with the existing CircuitBreaker module provides several benefits:

  • Consistent circuit breaker behavior across the application
  • Shared configuration and monitoring capabilities
  • Improved reliability through a well-tested implementation

4. Enhanced Logging and Monitoring

A metrics collection system has been implemented to track middleware execution performance and failures. The MiddlewareMetricsCollector class collects and reports metrics about middleware execution, including:

  • Execution time (min, max, average, total)
  • Success/failure counts and rates
  • Error types and counts
  • Last execution time

Guidelines for Developing Robust Middlewares

1. Error Handling

  • Always catch and handle exceptions specific to your middleware's functionality
  • Let unexpected exceptions propagate to be caught by the ExceptionHandlingMiddleware
  • Use appropriate HTTP status codes for different error conditions

2. Performance Considerations

  • Keep middleware execution time as short as possible
  • For long-running operations, consider using asynchronous processing
  • Be aware of the configured timeout for your middleware

3. Resource Management

  • Properly manage resources (file handles, database connections, etc.)
  • Use try-finally blocks to ensure resources are released even if an exception occurs
  • Be mindful of memory usage, especially when processing large requests

4. Middleware Dependencies

  • Keep dependencies between middlewares to a minimum
  • Document required middleware execution order in code comments
  • Use the MiddlewarePriorityAttribute to specify the desired execution order

5. Testing

  • Write unit tests for your middleware
  • Test both success and failure scenarios
  • Test with various input data, including edge cases
  • Test timeout scenarios

Monitoring and Troubleshooting

Metrics

The middleware system now collects detailed metrics about middleware execution. These metrics can be accessed via the MiddlewareMetricsCollector class:

// Get metrics for a specific middleware
$metrics = $metricsCollector->getMetrics(MyMiddleware::class);

// Get metrics for all middlewares
$allMetrics = $metricsCollector->getAllMetrics();

Circuit Breaker Status

You can interact with the circuit breaker for middlewares using the following methods:

// Check if a middleware is allowed to execute
$isAllowed = $circuitBreaker->isAllowed(MyMiddleware::class);

// Get the current state of the circuit for a middleware
$state = $circuitBreaker->getState(MyMiddleware::class); // Returns CircuitState enum

// Reset the circuit for a middleware
$circuitBreaker->reset(MyMiddleware::class);

// Get metrics for a middleware
$metrics = $circuitBreaker->getMetrics(MyMiddleware::class);

The circuit breaker state can be one of the following:

  • CircuitState::CLOSED: Normal operation, middleware is allowed to execute
  • CircuitState::OPEN: Too many failures, middleware is not allowed to execute
  • CircuitState::HALF_OPEN: Testing if the middleware is working again

Logging

The middleware system logs detailed information about middleware execution, including:

  • Start and end of middleware execution
  • Execution time
  • Errors and exceptions
  • Circuit breaker state changes

Check the application logs for entries with the middleware name to troubleshoot issues.

Conclusion

These improvements make the middleware system more robust by:

  • Ensuring exceptions are properly handled
  • Preventing long-running middlewares from blocking requests
  • Preventing repeatedly failing middlewares from being executed
  • Providing detailed metrics for monitoring and troubleshooting

By following the guidelines in this document, you can develop robust middlewares that contribute to a stable and reliable application.