AllocationPromise::then()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 3
1
<?php
2
namespace ResourcePool;
3
4
use React\Promise\PromiseInterface;
5
use React\Promise\RejectedPromise;
6
7
/**
8
 * @author Josh Di Fabio <[email protected]>
9
 *
10
 * @api
11
 */
12
class AllocationPromise implements PromiseInterface
13
{
14
    private $promise;
15
    private $resolver;
16
    private $result;
17
18
    public function __construct(PromiseInterface $promise, $resolver = null)
19
    {
20
        $this->promise = $promise;
21
        $this->resolver = $resolver;
22
    }
23
24
    /**
25
     * {@inheritdoc}
26
     */
27
    public function then(callable $fulfilledHandler = null, callable $errorHandler = null, callable $progressHandler = null)
28
    {
29
        return $this->promise->then($fulfilledHandler, $errorHandler, $progressHandler);
30
    }
31
32
    /**
33
     * Calls the specified handler when this promise is fulfilled.
34
     * 
35
     * If the handler returns a promise, 
36
     *
37
     * @param callable $handler
38
     * @return PromiseInterface
39
     */
40
    public function to($handler /*, $args… */)
41
    {
42
        $args = array_slice(func_get_args(), 1);
43
44
        return $this->then(
45
            function (Allocation $allocation) use ($handler, $args) {
46
                try {
47
                    $result = call_user_func_array($handler, $args);
48
                    $result = \React\Promise\resolve($result);
49
                    $result->then(array($allocation, 'releaseAll'), array($allocation, 'releaseAll'));
50
                } catch (\Exception $e) {
51
                    $result = new RejectedPromise($e);
52
                    $allocation->releaseAll();
53
                }
54
55
                return $result;
56
            }
57
        );
58
    }
59
60
    /**
61
     * Tries to return the allocation now, synchronously
62
     * 
63
     * If the pool does not have sufficient resources available then an exception is thrown and this
64
     * promise is rejected
65
     *
66
     * @return Allocation
67
     * @throws \RuntimeException thrown if the allocation fails or has previously failed
68
     */
69
    public function now()
70
    {
71
        return $this->getResult(false);
72
    }
73
    
74
    protected function getResult($burst)
75
    {
76
        if (null === $this->result) {
77
            $this->result = $this->resolve($burst);
78
        }
79
80
        if ($this->result instanceof \Exception) {
81
            throw $this->result;
82
        }
83
84
        return $this->result;
85
    }
86
    
87
    private function resolve($burst)
88
    {
89
        $result = null;
90
        
91
        $this->promise->then(
92
            function ($allocation) use (&$result) {
93
                $result = $allocation;
94
            },
95
            function ($error) use (&$result) {
96
                $result = $error;
97
            }
98
        );
99
100
        if (null === $result) {
101
            call_user_func($this->resolver, $burst);
102
        }
103
        
104
        return $result ?: new \LogicException('The resolver did not resolve the promise');
105
    }
106
}
107