Skip to content

Updates in ConnectionPool in order to use React\Async\await function #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 6, 2021

Conversation

iorsa
Copy link
Contributor

@iorsa iorsa commented Dec 6, 2021

According to some issues when ConnectionState enum (of $connectionFactory Closure/Class, which creates connection adapter) isn't Ready and retryWithDelay() function is called repeatedly.

I used to debug calls that used in your test.php file.

If you want better code readability you can use this variation of retryWithDelay() function (notice additional $selectConnectionDeferred):

protected function retryWithDelay(Deferred $deferred = null): \React\Promise\Promise
{
      if ($this->retryLimit !== null && $this->retryLimit < 1) {
          throw new ConnectionPoolException('No available connection to use');
      }

      $deferred ??= new Deferred();

      if (!$this->awaiting->contains($deferred)) {
          $this->awaiting->attach($deferred, 0);
      }

      if ($this->awaiting[$deferred] === $this->retryLimit) {
          $this->awaiting->detach($deferred);
          throw new ConnectionPoolException("No available connection to use; $this->retryLimit attempts were made");
      }

      $selectConnectionDeferred = new Deferred();

      $this->loop->addTimer($this->retryEverySec, function () use ($deferred, $selectConnectionDeferred) {
          $connectionAdapter = $this->selectConnection();

          if ($connectionAdapter) {
              $this->awaiting->detach($deferred);
              $selectConnectionDeferred->resolve(true);
              $deferred->resolve($connectionAdapter);
              return;
          }

          $this->awaiting[$deferred] = $this->awaiting[$deferred] + 1;
          $selectConnectionDeferred->resolve(false);
      });

      return $selectConnectionDeferred->promise()->then(function($connectionSelected) use ($deferred) {
          return $connectionSelected ? $deferred->promise() : $this->retryWithDelay($deferred);
      });
}

According to some issues when `ConnectionState` enum (of $connectionFactory Closure/Class, which creates connection adapter) isn't `Ready` and `retryWithDelay()` function is called repeatedly.

Btw, here is even more readable-"friendly" `retryWithDelay()` function variation:
```
protected function retryWithDelay(Deferred $deferred = null): \React\Promise\Promise
    {
        if ($this->retryLimit !== null && $this->retryLimit < 1) {
            throw new ConnectionPoolException('No available connection to use');
        }

        $deferred ??= new Deferred();

        if (!$this->awaiting->contains($deferred)) {
            $this->awaiting->attach($deferred, 0);
        }

        if ($this->awaiting[$deferred] === $this->retryLimit) {
            $this->awaiting->detach($deferred);
            throw new ConnectionPoolException("No available connection to use; $this->retryLimit attempts were made");
        }

        $selectConnectionDeferred = new Deferred();

        $this->loop->addTimer($this->retryEverySec, function () use ($deferred, $selectConnectionDeferred) {
            $connectionAdapter = $this->selectConnection();

            if ($connectionAdapter) {
                $this->awaiting->detach($deferred);
                $selectConnectionDeferred->resolve(true);
                $deferred->resolve($connectionAdapter);
                return;
            }

            $this->awaiting[$deferred] = $this->awaiting[$deferred] + 1;
            $selectConnectionDeferred->resolve(false);
        });

        return $selectConnectionDeferred->promise()->then(function($onnectionSelected) use ($deferred) {
            return $onnectionSelected ? $deferred->promise() : $this->retryWithDelay($deferred);
        });
    }
```
@iorsa iorsa changed the title Update ConnectionPool.php Updates in ConnectionPool in order to the use React\Async\await function Dec 6, 2021
@iorsa iorsa changed the title Updates in ConnectionPool in order to the use React\Async\await function Updates in ConnectionPool in order to use React\Async\await function Dec 6, 2021
@szado szado merged commit f4978a8 into szado:master Dec 6, 2021
@szado
Copy link
Owner

szado commented Dec 6, 2021

@iorsa thanks, I merged it: 399d5ce but after adding the retryLimit in test.php, a segmentation error occurred (instead of ConnectionLoopException). I rewrote retryWithDelay() with periodic timer and now it works as expected.

@iorsa iorsa deleted the patch-1 branch December 7, 2021 04:56
@iorsa
Copy link
Contributor Author

iorsa commented Dec 7, 2021

@szado hm, I also used retryLimit param to limit the amount of retries and haven't discovered this problem (tested on linux only, though). Great job! It looks like a better approach anyway, than using addTimer() in nested self function calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants