Issues (6)

src/Features/Keepalive.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * Service keepalive (agent-check updater)
4
 * User: moyo
5
 * Date: 18/09/2017
6
 * Time: 4:18 PM
7
 */
8
9
namespace Carno\Consul\Features;
10
11
use Carno\Consul\APIs\AgentCheckUpdater;
12
use Carno\Consul\APIs\AgentServiceRegister;
13
use Carno\Consul\Contracts\Defaults;
14
use Carno\Consul\Results\Failed;
15
use Carno\Consul\Types\Result;
16
use Carno\Consul\Types\Service;
17
use function Carno\Coroutine\co;
18
use function Carno\Coroutine\go;
19
use function Carno\Coroutine\msleep;
20
use Carno\Timer\Timer;
21
use Generator;
22
use Throwable;
23
24
class Keepalive
25
{
26
    /**
27
     * @var Service
28
     */
29
    private $service = null;
30
31
    /**
32
     * @var string
33
     */
34
    private $identify = null;
35
36
    /**
37
     * @var string
38
     */
39
    private $daemon = null;
40
41
    /**
42
     * Keepalive constructor.
43
     * @param Service $service
44
     * @param int $heartbeat
45
     */
46
    public function __construct(Service $service, int $heartbeat)
47
    {
48
        $this->service = $service;
49
        $this->identify = sprintf('service:%s', $service->id());
50
51
        $this->start($heartbeat);
52
    }
53
54
    /**
55
     * @param int $heartbeat
56
     */
57
    private function start(int $heartbeat) : void
58
    {
59
        $this->daemon = Timer::loop($heartbeat * 1000, co(function () {
60
            yield $this->updating();
61
        }));
62
63
        logger('consul')->info(
64
            'Agent check updater started',
65
            ['id' => $this->identify, 'agent' => $this->service->hosting()]
66
        );
67
68
        go($this->updating());
69
    }
70
71
    /**
72
     * @return void
73
     */
74
    public function shutdown() : void
75
    {
76
        $this->daemon && Timer::clear($this->daemon);
77
        logger('consul')->info('Agent check updater stopped', ['id' => $this->identify]);
78
    }
79
80
    /**
81
     * @return Generator|void
82
     */
83
    private function updating()
84
    {
85
        /**
86
         * @var Result $krr
87
         */
88
89
        try {
90
            $krr = yield (new AgentCheckUpdater($this->service->hosting()))
91
                ->related($this->identify, AgentCheckUpdater::PASS)
92
                ->signature()
93
                ->result()
94
            ;
95
        } catch (Throwable $e) {
96
            $krr = new Failed(sprintf('%s::%s', get_class($e), $e->getMessage()));
97
        }
98
99
        if ($krr->success()) {
100
            logger('consul')->debug(
101
                'Agent check update success',
102
                ['id' => $this->identify, 'agent' => $this->service->hosting()]
103
            );
104
        } else {
105
            logger('consul')->warning(
106
                'Agent check update failed',
107
                ['id' => $this->identify, 'agent' => $this->service->hosting(), 'reason' => $krr->reason()]
0 ignored issues
show
The method reason() does not exist on Carno\Consul\Types\Result. It seems like you code against a sub-type of Carno\Consul\Types\Result such as Carno\Consul\Results\Failed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

107
                ['id' => $this->identify, 'agent' => $this->service->hosting(), 'reason' => $krr->/** @scrutinizer ignore-call */ reason()]
Loading history...
108
            );
109
110
            yield msleep($sleep = rand(Defaults::ERROR_RETRY_MIN, Defaults::ERROR_RETRY_MAX));
111
112
            yield $this->recovering();
113
        }
114
    }
115
116
    /**
117
     * @return Generator|void
118
     */
119
    private function recovering()
120
    {
121
        /**
122
         * @var Service $service
123
         * @var Result $srr
124
         */
125
126
        try {
127
            $srr = yield (new AgentServiceRegister($this->service->agent()))
128
                ->service($this->service)
129
                ->result()
130
            ;
131
        } catch (Throwable $e) {
132
            $srr = new Failed(sprintf('%s::%s', get_class($e), $e->getMessage()));
133
        }
134
135
        if ($srr->success()) {
136
            logger('consul')->info(
137
                'Service recovering success',
138
                ['id' => $this->identify, 'agent' => $this->service->hosting()]
139
            );
140
        } else {
141
            logger('consul')->warning(
142
                'Service recovering failed',
143
                ['id' => $this->identify, 'agent' => $this->service->hosting(), 'reason' => $srr->reason()]
144
            );
145
        }
146
    }
147
}
148