Completed
Pull Request — master (#3)
by Dan
06:36
created

ReactAwareCurlFactory::decrementCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Nopolabs\Yabot\Guzzle;
4
5
6
use GuzzleHttp\Handler\CurlFactory;
7
use GuzzleHttp\Handler\CurlFactoryInterface;
8
use GuzzleHttp\Handler\CurlMultiHandler;
9
use GuzzleHttp\Handler\EasyHandle;
10
use Psr\Http\Message\RequestInterface;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
use React\EventLoop\LoopInterface;
14
use React\EventLoop\Timer\TimerInterface;
15
16
class ReactAwareCurlFactory implements CurlFactoryInterface
17
{
18
    private $eventLoop;
19
    private $logger;
20
    private $factory;
21
    private $count;
22
    private $handler;
23
24
    /** @var TimerInterface */
25
    private $timer;
26
27
    public function __construct(LoopInterface $eventLoop, LoggerInterface $logger = null)
28
    {
29
        $this->eventLoop = $eventLoop;
30
        $this->logger = $logger ?? new NullLogger();
31
32
        $this->factory = new CurlFactory(50);
33
        $this->count = 0;
34
    }
35
36
    public function setHandler(CurlMultiHandler $handler)
37
    {
38
        $this->handler = $handler;
39
    }
40
41
    public function tick()
42
    {
43
        $this->handler->tick();
44
45
        if ($this->count === 0 && \GuzzleHttp\Promise\queue()->isEmpty()) {
46
            $this->stopTimer();
47
        }
48
    }
49
50
    /**
51
     * Creates a cURL handle resource.
52
     *
53
     * @param RequestInterface $request Request
54
     * @param array $options Transfer options
55
     *
56
     * @return EasyHandle
57
     * @throws \RuntimeException when an option cannot be applied
58
     */
59
    public function create(RequestInterface $request, array $options)
60
    {
61
        $easy = $this->factory->create($request, $options);
62
63
        $this->incrementCount();
64
65
        return $easy;
66
    }
67
68
    /**
69
     * Release an easy handle, allowing it to be reused or closed.
70
     *
71
     * This function must call unset on the easy handle's "handle" property.
72
     *
73
     * @param EasyHandle $easy
74
     */
75
    public function release(EasyHandle $easy)
76
    {
77
        $this->factory->release($easy);
78
79
        $this->decrementCount();
80
    }
81
82
    private function incrementCount()
83
    {
84
        if ($this->count === 0) {
85
            $this->startTimer();
86
        }
87
88
        $this->count++;
89
    }
90
91
    private function decrementCount()
92
    {
93
        $this->count--;
94
    }
95
96
    private function startTimer()
97
    {
98
        if ($this->timer === null) {
99
            $this->timer = $this->eventLoop->addPeriodicTimer(0, [$this, 'tick']);
100
101
            $this->logger->debug('ReactAwareCurlFactory started periodic queue processing');
102
        }
103
    }
104
105
    private function stopTimer()
106
    {
107
        if ($this->timer !== null) {
108
            $this->timer->cancel();
109
            $this->timer = null;
110
111
            $this->logger->debug('ReactAwareCurlFactory stopped periodic queue processing');
112
        }
113
    }
114
}