Skip to content

Commit ddb3b56

Browse files
committed
Update pool connection creation
1 parent 2d9e97a commit ddb3b56

File tree

4 files changed

+39
-16
lines changed

4 files changed

+39
-16
lines changed

lib/AbstractConnection.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ private function send(string $methodName, ...$args): Promise {
5858
yield $this->busy->promise();
5959
}
6060

61-
return yield $this->handle->{$methodName}(...$args);
61+
return yield ([$this->handle, $methodName])(...$args);
6262
});
6363
}
6464

65-
return $this->handle->{$methodName}(...$args);
65+
return ([$this->handle, $methodName])(...$args);
6666
}
6767

6868
/**

lib/AbstractPool.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ abstract class AbstractPool implements Pool {
3232
/** @var callable */
3333
private $push;
3434

35+
/** @var int */
36+
private $pending = 0;
37+
3538
/**
3639
* @return \Amp\Promise<\Amp\Postgres\Connection>
3740
*
@@ -72,10 +75,16 @@ public function getIdleConnectionCount(): int {
7275

7376
/**
7477
* @param \Amp\Postgres\Connection $connection
78+
*
79+
* @throws \Error if the connection is already part of this pool or if the connection is dead.
7580
*/
7681
protected function addConnection(Connection $connection) {
7782
if (isset($this->connections[$connection])) {
78-
return;
83+
throw new \Error("Connection is already a part of this pool");
84+
}
85+
86+
if (!$connection->isAlive()) {
87+
throw new \Error("The connection is dead");
7988
}
8089

8190
$this->connections->attach($connection);
@@ -92,17 +101,13 @@ protected function addConnection(Connection $connection) {
92101
* @resolve \Amp\Postgres\Connection
93102
*/
94103
private function pop(): \Generator {
95-
while ($this->promise !== null) {
96-
try {
97-
yield $this->promise; // Prevent simultaneous connection creation.
98-
} catch (\Throwable $exception) {
99-
// Ignore failure or cancellation of other operations.
100-
}
104+
while ($this->promise !== null && $this->connections->count() + $this->pending >= $this->getMaxConnections()) {
105+
yield $this->promise; // Prevent simultaneous connection creation when connection count is at maximum - 1.
101106
}
102107

103108
while ($this->idle->isEmpty()) { // While loop to ensure an idle connection is available after promises below are resolved.
104109
try {
105-
if ($this->connections->count() >= $this->getMaxConnections()) {
110+
if ($this->connections->count() + $this->pending >= $this->getMaxConnections()) {
106111
// All possible connections busy, so wait until one becomes available.
107112
$this->deferred = new Deferred;
108113
yield $this->promise = $this->deferred->promise(); // May be resolved with defunct connection.

test/AbstractPoolTest.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,7 @@ abstract protected function createPool(array $connections): Pool;
2727
*/
2828
protected function createConnection(): Connection {
2929
$mock = $this->createMock(Connection::class);
30-
$mock->method('isAlive')
31-
->willReturnCallback(static function () {
32-
static $count = 0;
33-
return $count++ < 3; // Force defunct connection after 3 operations.
34-
});
35-
30+
$mock->method('isAlive')->willReturn(true);
3631
return $mock;
3732
}
3833

test/AggregatePoolTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Amp\Postgres\Test;
44

55
use Amp\Postgres\AggregatePool;
6+
use Amp\Postgres\Connection;
67
use Amp\Postgres\Pool;
78

89
class AggregatePoolTest extends AbstractPoolTest {
@@ -47,4 +48,26 @@ public function testGetIdleConnectionCount() {
4748
$promise = $pool->query("SELECT 1");
4849
$this->assertSame(1, $pool->getIdleConnectionCount());
4950
}
51+
52+
/**
53+
* @expectedException \Error
54+
* @expectedExceptionMessage Connection is already a part of this pool
55+
*/
56+
public function testDoubleAddConnection() {
57+
$pool = $this->createPool([]);
58+
$connection = $this->createConnection();
59+
$pool->addConnection($connection);
60+
$pool->addConnection($connection);
61+
}
62+
63+
/**
64+
* @expectedException \Error
65+
* @expectedExceptionMessage The connection is dead
66+
*/
67+
public function testAddDeadConnection() {
68+
$pool = $this->createPool([]);
69+
$connection = $this->createMock(Connection::class);
70+
$connection->method('isAlive')->willReturn(false);
71+
$pool->addConnection($connection);
72+
}
5073
}

0 commit comments

Comments
 (0)