Flesh out the connection pool class.
This commit is contained in:
parent
07b73e7f7f
commit
f5abbcb8c9
@ -15,7 +15,8 @@
|
||||
"dotenv-org/phpdotenv-vault": "^0.2.4",
|
||||
"react/react": "^1.4",
|
||||
"robmorgan/phinx": "^0.16.1",
|
||||
"react/mysql": "^0.7dev"
|
||||
"react/mysql": "^0.7dev",
|
||||
"react/async": "^4.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.1",
|
||||
|
2
app/composer.lock
generated
2
app/composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "525ed6c2ef7a52e8447108c1427f1b7d",
|
||||
"content-hash": "df12c4f8e3bfd8ecbaa4864a9d702c27",
|
||||
"packages": [
|
||||
{
|
||||
"name": "cakephp/chronos",
|
||||
|
@ -32,6 +32,3 @@ try {
|
||||
fprintf(STDERR, $e->getMessage() . "\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -15,7 +15,13 @@ interface ConnectionPoolInterface
|
||||
* @return bool
|
||||
*/
|
||||
public function hasIdleConnection(): bool;
|
||||
public function setWaitTimeout(int $seconds): void;
|
||||
|
||||
/**
|
||||
* Sets the new wait timeout for acquiring a connection.
|
||||
*
|
||||
* @param int $ms The amount of time in seconds.
|
||||
*/
|
||||
public function setWaitTimeout(int $s): void;
|
||||
public function getWaitTimeout(): int;
|
||||
public function getConnectionLimit(): int;
|
||||
|
||||
|
@ -2,65 +2,84 @@
|
||||
|
||||
namespace Slovocast\Infrastructure\Database;
|
||||
|
||||
use React\Mysql\MysqlClient;
|
||||
use Slovocast\Infrastructure\Api\Database\ConnectionPoolInterface;
|
||||
use Slovocast\Infrastructure\Api\Database\PooledConnectionInterface;
|
||||
use SplObjectStorage;
|
||||
|
||||
class ConnectionPool implements ConnectionPoolInterface
|
||||
{
|
||||
/**
|
||||
* Set a default wait timeout for acquiring a connection to 100ms
|
||||
*/
|
||||
const int DEFAULT_WAIT_TIMEOUT = 100;
|
||||
private array $idleConnections;
|
||||
private array $activeConnections;
|
||||
private int $waitTimeout;
|
||||
private SplObjectStorage $idleConnections;
|
||||
private SplObjectStorage $activeConnections;
|
||||
private ConnectionPoolConfig $config;
|
||||
|
||||
public function __construct(ConnectionPoolConfig $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
for ($i = 0; $i < $config->getTotalConnections(); $i++) {
|
||||
$this->idleConnections[] = new MysqlClient($this->config->getDsn());
|
||||
$this->idleConnections = new SplObjectStorage();
|
||||
$this->activeConnections = new SplObjectStorage();
|
||||
|
||||
for ($i = 0; $i < $this->config->getTotalConnections(); $i++) {
|
||||
$pooledConnection = new PooledConnection($this->config->getDsnString());
|
||||
$this->idleConnections->attach($$pooledConnection);
|
||||
}
|
||||
|
||||
$this->waitTimeout = $config->getPoolWaitTimeout();
|
||||
}
|
||||
|
||||
public function getTotalIdleConnections(): int
|
||||
{
|
||||
// TODO: Implement getTotalIdleConnections() method.
|
||||
return $this->idleConnections->count();
|
||||
}
|
||||
|
||||
public function getTotalActiveConnections(): int
|
||||
{
|
||||
// TODO: Implement getTotalActiveConnections() method.
|
||||
return $this->activeConnections->count();
|
||||
}
|
||||
|
||||
public function hasIdleConnection(): bool
|
||||
{
|
||||
// TODO: Implement hasIdleConnection() method.
|
||||
return $this->idleConnections->count() > 0;
|
||||
}
|
||||
|
||||
public function setWaitTimeout(int $seconds): void
|
||||
public function setWaitTimeout(int $s): void
|
||||
{
|
||||
// TODO: Implement setWaitTimeout() method.
|
||||
$this->waitTimeout = $s;
|
||||
}
|
||||
|
||||
public function getWaitTimeout(): int
|
||||
{
|
||||
// TODO: Implement getWaitTimeout() method.
|
||||
return $this->waitTimeout;
|
||||
}
|
||||
|
||||
public function getConnectionLimit(): int
|
||||
{
|
||||
// TODO: Implement getConnectionLimit() method.
|
||||
return $this->config->getTotalConnections();
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO Throw an exception when a total timeout is exceeded. We do not want
|
||||
* to get into an infinite loop.
|
||||
*
|
||||
* @return PooledConnectionInterface
|
||||
*/
|
||||
public function getConnection(): PooledConnectionInterface
|
||||
{
|
||||
// TODO: Implement getConnection() method.
|
||||
if (!$this->hasIdleConnection()) {
|
||||
\React\Async\delay((float) $this->getWaitTimeout());
|
||||
return this->getConnection();
|
||||
}
|
||||
|
||||
$conn = $this->idleConnections->current();
|
||||
$this->idleConnections->detach($conn);
|
||||
$this->activeConnections->attach($conn);
|
||||
return $conn;
|
||||
}
|
||||
|
||||
public function releaseConnection(PooledConnectionInterface $connection): void
|
||||
{
|
||||
// TODO: Implement releaseConnection() method.
|
||||
if ($this->activeConnections->contains($connection)) {
|
||||
$this->activeConnections->detach($connection);
|
||||
$this->idleConnections->attach($connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,19 @@
|
||||
|
||||
namespace Slovocast\Infrastructure\Database;
|
||||
|
||||
use React\Mysql\MysqlClient;
|
||||
|
||||
class ConnectionPoolConfig
|
||||
{
|
||||
const DEFAULT_WAIT_TIMEOUT = 60;
|
||||
const DEFAULT_TOTAL_CONNECTIONS = 10;
|
||||
|
||||
public function __construct(
|
||||
public readonly string $username,
|
||||
public readonly string $password,
|
||||
public readonly string $database,
|
||||
public readonly string $host,
|
||||
protected int $port = 3306,
|
||||
protected int $poolWaitTimeout = ConnectionPool::DEFAULT_WAIT_TIMEOUT,
|
||||
protected int $totalConnections = 10,
|
||||
protected int $poolWaitTimeout = self::DEFAULT_WAIT_TIMEOUT,
|
||||
protected int $totalConnections = self::DEFAULT_TOTAL_CONNECTIONS
|
||||
) { }
|
||||
|
||||
public function getPort(): int
|
||||
@ -31,7 +32,7 @@ class ConnectionPoolConfig
|
||||
return $this->totalConnections;
|
||||
}
|
||||
|
||||
public function getDsn(): string
|
||||
public function getDsnString(): string
|
||||
{
|
||||
return sprintf(
|
||||
"%s:%s@%s/%s",
|
||||
|
Loading…
Reference in New Issue
Block a user