clue/connection-manager-extra
Extra connector decorators for ReactPHP Socket. Wrap ConnectorInterface to add retries, timeouts, delays, rejection rules, swapping, consecutive/random selection, concurrency limits and selective routing—without changing your async connect() code.
composer require clue/connection-manager-extra
composer require react/socket
use React\Socket\Connector;
use ConnectionManager\Extra\ConnectionManagerTimeout;
$connector = new Connector();
$timeoutConnector = new ConnectionManagerTimeout($connector, 5.0); // 5-second timeout
$timeoutConnector->connect('example.com:80')
->then(function ($stream) {
$stream->write("GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");
$stream->end();
})
->otherwise(function ($exception) {
echo "Connection failed: " . $exception->getMessage();
});
Use ConnectionManagerRepeat to retry failed connections:
$retryConnector = new ConnectionManagerRepeat($connector, 3); // 3 total attempts
$retryConnector->connect('unreliable.example.com:80')->then(...);
Combine decorators for complex workflows:
$baseConnector = new Connector();
$delayedConnector = new ConnectionManagerDelay($baseConnector, 1.0); // 1s delay
$retryConnector = new ConnectionManagerRepeat($delayedConnector, 3); // 3 retries
$timeoutConnector = new ConnectionManagerTimeout($retryConnector, 10.0); // 10s timeout
Route connections based on host/port patterns:
$blocked = new ConnectionManagerReject('Blocked');
$delayed = new ConnectionManagerDelay($connector, 2.0);
$selective = new ConnectionManagerSelective([
'ads.example.com' => $blocked,
'*.example.com:80' => $delayed,
'*' => $connector // Default fallback
]);
Try multiple connectors in parallel:
$connector1 = new ConnectionManagerTimeout($baseConnector, 2.0);
$connector2 = new ConnectionManagerDelay($baseConnector, 0.5);
$concurrent = new ConnectionManagerConcurrent([$connector1, $connector2]);
Replace connectors at runtime (e.g., for failover):
$swappable = new ConnectionManagerSwappable($connector);
$swappable->setConnectionManager($newConnector); // Swap during execution
$timeout values are realistic for your network (e.g., 5s for local, 10s+ for remote).$retryConnector = new ConnectionManagerRepeat($connector, 3);
$retryConnector->connect('...')->otherwise(function ($e) {
\Log::error("Connection failed: " . $e->getMessage());
});
*.example.com matches sub.example.com but not example.com. Use example.com + *.example.com for full coverage.min-max (e.g., *:80-81) for port ranges. Invalid formats throw InvalidArgumentException.http:// or https://) when matching hosts.ConnectionManagerConcurrent is faster but uses more resources. Prefer Consecutive for sequential fallbacks.Timeout/Delay now auto-detect the default loop (PHP 8.1+). Explicitly pass $loop only if needed.ConnectionManagerReject to implement dynamic blocking (e.g., API-based blacklists).RetryWithDelayTimeout).ConnectionManagerSwappable to dynamically switch connectors based on runtime conditions (e.g., load balancing).ConnectionManagerRepeat can cause hangs.*:80 matches example.com:80 but not example.com:443. Use explicit rules for HTTPS.$loop arguments may cause race conditions. Stick to one loop per application.$stream->close() or $stream->end() to avoid memory leaks in long-running connections.React\EventLoop\Factory::create() once and reuse it across decorators:
$loop = React\EventLoop\Factory::create();
$connector = new Connector($loop);
AppServiceProvider:
$this->app->singleton('retry.connector', function ($app) {
return new ConnectionManagerRepeat($app['socket.connector'], 3);
});
spatie/async or reactphp/async for non-blocking Laravel jobs:
use React\Async\AsyncJob;
AsyncJob::perform(function () use ($connector) {
return $connector->connect('...')->then(...);
});
How can I help you explore Laravel packages today?