-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
When Redis pipeline() is used inside coroutines, the Redis connection is not returned to the pool after the pipeline closure finishes. This is a problem for long-running coroutines.
To reproduce:
- Set the Redis config's
pool.max_connectionsto2. - Add the controller below and call each endpoint 5-10 times. The
directendpoint will not cause connection pool exhaustion. Thepipelineendpoint will cause a connection pool exception after 2 requests.
<?php
declare(strict_types=1);
namespace App\Controller;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\Redis\Redis;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\Coroutine\Coroutine;
/**
* Demonstrates Redis connection pool exhaustion with pipelines
*
* Set Redis pool max_connections to 2 in config/autoload/redis.php,
* then call each of the endpoints 5-10 times.
*/
#[Controller]
class RedisTestController
{
public function __construct(
protected Redis $redis,
protected ResponseInterface $response,
) {}
/**
* Tests direct Redis commands in coroutines
*/
#[RequestMapping(path: "/redis/direct", methods: ["GET"])]
public function direct()
{
Coroutine::create(function () {
$key1 = "direct:" . uniqid();
$key2 = "direct::" . uniqid();
// Each command releases the connection after use
$this->redis->set($key1, "value-{$key1}");
$this->redis->set($key2, "value-{$key2}");
// Sleep to simulate work - connection is already released
sleep(60);
});
return $this->response->json(['message' => 'success']);
}
/**
* Tests pipeline Redis commands in coroutines
*/
#[RequestMapping(path: "/redis/pipeline", methods: ["GET"])]
public function pipeline()
{
Coroutine::create(function () {
$key1 = "pipeline:" . uniqid();
$key2 = "pipeline::" . uniqid();
// Pipeline doesn't release connection properly
$this->redis->pipeline(function ($pipe) use ($key1, $key2) {
$pipe->set($key1, "value-{$key1}");
$pipe->set($key2, "value-{$key2}");
});
// Sleep to simulate work - connection is still held!
sleep(60);
});
return $this->response->json(['message' => 'success']);
}
}It would be great if pipeline() could be made coroutine-friendly.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working