Skip to content

Commit

Permalink
feat: add error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
allsilaevex committed Mar 11, 2024
1 parent e5985da commit 772d116
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 81 deletions.
31 changes: 19 additions & 12 deletions src/connection-pool/ConnectionPoolFactory.php
Expand Up @@ -15,7 +15,6 @@
use Allsilaevex\Pool\Hook\PoolItemHookManager;
use Allsilaevex\Pool\PoolItemFactoryInterface;
use Allsilaevex\Pool\PoolItemWrapperInterface;
use Allsilaevex\Pool\Hook\PoolItemHookInterface;
use Allsilaevex\Pool\TimerTask\TimerTaskInterface;
use Allsilaevex\Pool\TimerTask\TimerTaskScheduler;
use Allsilaevex\ConnectionPool\Tasks\ResizerTimerTask;
Expand All @@ -27,6 +26,7 @@
use function count;
use function substr;
use function uniqid;
use function array_map;

/**
* @template TConnection of object
Expand All @@ -43,13 +43,13 @@ class ConnectionPoolFactory
protected float $leakDetectionThresholdSec;
protected float $maxItemReservingForUpdateWaitingTimeSec;

/** @var list<PoolItemHookInterface<TConnection>> */
protected array $hooks;
/** @var list<callable(TConnection): bool> */
protected array $checkers;

protected LoggerInterface $logger;

/** @var list<TimerTaskInterface<PoolItemWrapperInterface<TConnection>>> */
protected array $poolItemTimerTasks;
/** @var list<KeepaliveCheckerInterface<TConnection>> */
protected array $keepaliveCheckers;

/**
* @param positive-int $size
Expand All @@ -59,9 +59,9 @@ public function __construct(
protected int $size,
protected PoolItemFactoryInterface $factory,
) {
$this->hooks = [];
$this->checkers = [];
$this->logger = new NullLogger();
$this->poolItemTimerTasks = [];
$this->keepaliveCheckers = [];

$this->minimumIdle = $this->size;
$this->autoReturn = true;
Expand Down Expand Up @@ -200,7 +200,7 @@ public function setReturningTimeoutSec(float $returningTimeoutSec): self
*/
public function setConnectionChecker(callable $checker): self
{
$this->hooks[] = new ConnectionCheckHook($checker);
$this->checkers[] = $checker;

return $this;
}
Expand All @@ -212,8 +212,7 @@ public function setConnectionChecker(callable $checker): self
*/
public function setKeepaliveChecker(KeepaliveCheckerInterface $keepaliveChecker): self
{
/** @psalm-suppress InvalidPropertyAssignmentValue */
$this->poolItemTimerTasks[] = new KeepaliveCheckTimerTask($keepaliveChecker);
$this->keepaliveCheckers[] = $keepaliveChecker;

return $this;
}
Expand Down Expand Up @@ -245,15 +244,23 @@ public function instantiate(string $name = ''): PoolInterface
$poolItemUpdaterTimerTask = new PoolItemUpdaterTimerTask(
intervalSec: $this->maxLifetimeSec / 10,
maxLifetimeSec: $this->maxLifetimeSec,
logger: $this->logger,
maxItemReservingWaitingTimeSec: $this->maxItemReservingForUpdateWaitingTimeSec,
);

$poolItemTimerTasks = array_map(
fn (KeepaliveCheckerInterface $checker) => new KeepaliveCheckTimerTask($this->logger, $checker),
$this->keepaliveCheckers,
);

/** @var TimerTaskScheduler<PoolItemWrapperInterface<TConnection>> $poolItemTimerTaskScheduler */
$poolItemTimerTaskScheduler = new TimerTaskScheduler([
$poolItemUpdaterTimerTask,
...$this->poolItemTimerTasks,
...$poolItemTimerTasks,
]);

$hooks = array_map(fn (callable $checker) => new ConnectionCheckHook($checker, $this->logger), $this->checkers);

/**
* @var Pool<TConnection> $pool
* @psalm-suppress InvalidArgument
Expand All @@ -267,7 +274,7 @@ public function instantiate(string $name = ''): PoolInterface
),
logger: $this->logger,
timerTaskScheduler: $timerTaskScheduler,
poolItemHookManager: count($this->hooks) > 0 ? new PoolItemHookManager($this->hooks) : null,
poolItemHookManager: count($hooks) > 0 ? new PoolItemHookManager($hooks) : null,
);

return $pool;
Expand Down
11 changes: 9 additions & 2 deletions src/connection-pool/Hooks/ConnectionCheckHook.php
Expand Up @@ -4,9 +4,11 @@

namespace Allsilaevex\ConnectionPool\Hooks;

use Psr\Log\LoggerInterface;
use Allsilaevex\Pool\Hook\PoolItemHook;
use Allsilaevex\Pool\PoolItemWrapperInterface;
use Allsilaevex\Pool\Hook\PoolItemHookInterface;
use Allsilaevex\Pool\Exceptions\PoolItemCreationException;

/**
* @template TItem of object
Expand All @@ -19,6 +21,7 @@
*/
public function __construct(
protected mixed $checker,
protected LoggerInterface $logger,
) {
}

Expand All @@ -30,11 +33,15 @@ public function invoke(PoolItemWrapperInterface $poolItemWrapper): void
$item = $poolItemWrapper->getItem();
$checker = $this->checker;

if ($checker($item)) {
if (is_null($item) || $checker($item)) {
return;
}

$poolItemWrapper->recreateItem();
try {
$poolItemWrapper->recreateItem();
} catch (PoolItemCreationException $exception) {
$this->logger->error('Can\'t recreate item: ' . $exception->getMessage(), ['item_id' => $poolItemWrapper->getId()]);
}
}

public function getHook(): PoolItemHook
Expand Down
7 changes: 6 additions & 1 deletion src/connection-pool/Hooks/ConnectionResetHook.php
Expand Up @@ -8,6 +8,8 @@
use Allsilaevex\Pool\PoolItemWrapperInterface;
use Allsilaevex\Pool\Hook\PoolItemHookInterface;

use function is_null;

/**
* @template TItem of object
* @implements PoolItemHookInterface<TItem>
Expand All @@ -27,9 +29,12 @@ public function __construct(
*/
public function invoke(PoolItemWrapperInterface $poolItemWrapper): void
{
$item = $poolItemWrapper->getItem();
$resetter = $this->resetter;

$resetter($poolItemWrapper->getItem());
if (!is_null($item)) {
$resetter($item);
}
}

public function getHook(): PoolItemHook
Expand Down
2 changes: 1 addition & 1 deletion src/connection-pool/KeepaliveCheckerInterface.php
Expand Up @@ -10,7 +10,7 @@
interface KeepaliveCheckerInterface
{
/**
* @param TConnection $connection
* @param TConnection|null $connection
*/
public function check(mixed $connection): bool;

Expand Down
17 changes: 9 additions & 8 deletions src/connection-pool/Tasks/KeepaliveCheckTimerTask.php
Expand Up @@ -4,12 +4,12 @@

namespace Allsilaevex\ConnectionPool\Tasks;

use LogicException;
use Psr\Log\LoggerInterface;
use Allsilaevex\Pool\PoolItemState;
use Allsilaevex\Pool\PoolItemWrapperInterface;
use Allsilaevex\Pool\TimerTask\TimerTaskInterface;
use Allsilaevex\ConnectionPool\KeepaliveCheckerInterface;
use Allsilaevex\Pool\Exceptions\PoolItemRemovedException;
use Allsilaevex\Pool\Exceptions\PoolItemCreationException;

use function is_null;

Expand All @@ -23,6 +23,7 @@
* @param KeepaliveCheckerInterface<TItem> $keepaliveChecker
*/
public function __construct(
protected LoggerInterface $logger,
protected KeepaliveCheckerInterface $keepaliveChecker,
) {
}
Expand All @@ -43,14 +44,14 @@ public function run(int $timerId, mixed $runnerRef): void
return;
}

try {
$isAlive = $this->keepaliveChecker->check($runner->getItem());
} catch (PoolItemRemovedException) {
throw new LogicException();
}
$isAlive = $this->keepaliveChecker->check($runner->getItem());

if (!$isAlive) {
$runner->recreateItem();
try {
$runner->recreateItem();
} catch (PoolItemCreationException $exception) {
$this->logger->error('Can\'t recreate item: ' . $exception->getMessage(), ['item_id' => $runner->getId()]);
}
}

$runner->setState(PoolItemState::IDLE);
Expand Down
9 changes: 8 additions & 1 deletion src/connection-pool/Tasks/PoolItemUpdaterTimerTask.php
Expand Up @@ -4,9 +4,11 @@

namespace Allsilaevex\ConnectionPool\Tasks;

use Psr\Log\LoggerInterface;
use Allsilaevex\Pool\PoolItemState;
use Allsilaevex\Pool\PoolItemWrapperInterface;
use Allsilaevex\Pool\TimerTask\TimerTaskInterface;
use Allsilaevex\Pool\Exceptions\PoolItemCreationException;

use function is_null;

Expand All @@ -19,6 +21,7 @@
public function __construct(
public float $intervalSec,
public float $maxLifetimeSec,
public LoggerInterface $logger,
public float $maxItemReservingWaitingTimeSec = .0,
) {
}
Expand Down Expand Up @@ -53,7 +56,11 @@ public function run(int $timerId, mixed $runnerRef): void
}

if ($runner->stats()['item_lifetime_sec'] > $this->maxLifetimeSec) {
$runner->recreateItem();
try {
$runner->recreateItem();
} catch (PoolItemCreationException $exception) {
$this->logger->error('Can\'t recreate item: ' . $exception->getMessage(), ['item_id' => $runner->getId()]);
}
}

$runner->setState(PoolItemState::IDLE);
Expand Down
1 change: 1 addition & 0 deletions src/connection-pool/Tasks/ResizerTimerTask.php
Expand Up @@ -36,6 +36,7 @@ public function __construct(
*/
public function run(int $timerId, mixed $runnerRef): void
{
/** @var PoolControlInterface<TItem>|null $runner */
$runner = $runnerRef->get();

if (is_null($runner)) {
Expand Down

0 comments on commit 772d116

Please sign in to comment.