summaryrefslogtreecommitdiffstats
path: root/vendor/clue/connection-manager-extra/src/Multiple/ConnectionManagerConsecutive.php
blob: 1474b85d68083ed4a65386019ceb658c68ffd42f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

namespace ConnectionManager\Extra\Multiple;

use React\Socket\ConnectorInterface;
use React\Promise;
use UnderflowException;
use React\Promise\CancellablePromiseInterface;

class ConnectionManagerConsecutive implements ConnectorInterface
{
    protected $managers;

    /**
     *
     * @param ConnectorInterface[] $managers
     */
    public function __construct(array $managers)
    {
        if (!$managers) {
            throw new \InvalidArgumentException('List of connectors must not be empty');
        }
        $this->managers = $managers;
    }

    public function connect($uri)
    {
        return $this->tryConnection($this->managers, $uri);
    }

    /**
     *
     * @param ConnectorInterface[] $managers
     * @param string $uri
     * @return Promise
     * @internal
     */
    public function tryConnection(array $managers, $uri)
    {
        return new Promise\Promise(function ($resolve, $reject) use (&$managers, &$pending, $uri) {
            $try = function () use (&$try, &$managers, $uri, $resolve, $reject, &$pending) {
                if (!$managers) {
                    return $reject(new UnderflowException('No more managers to try to connect through'));
                }

                $manager = array_shift($managers);
                $pending = $manager->connect($uri);
                $pending->then($resolve, $try);
            };

            $try();
        }, function ($_, $reject) use (&$managers, &$pending) {
            // stop retrying, reject results and cancel pending attempt
            $managers = array();
            $reject(new \RuntimeException('Cancelled'));

            if ($pending instanceof CancellablePromiseInterface) {
                $pending->cancel();
            }
        });
    }
}