Completed
Push — master ( 79ef00...d11daa )
by Alexandru
01:30 queued 11s
created

StartWebSocketServer::configureRestartTimer()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 2
nc 1
nop 0
1
<?php
2
3
namespace BeyondCode\LaravelWebSockets\Console;
4
5
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
6
use BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter;
7
use BeyondCode\LaravelWebSockets\Server\Logger\ConnectionLogger;
8
use BeyondCode\LaravelWebSockets\Server\Logger\HttpLogger;
9
use BeyondCode\LaravelWebSockets\Server\Logger\WebsocketsLogger;
10
use BeyondCode\LaravelWebSockets\Server\WebSocketServerFactory;
11
use BeyondCode\LaravelWebSockets\Statistics\DnsResolver;
12
use BeyondCode\LaravelWebSockets\Statistics\Logger\StatisticsLogger as StatisticsLoggerInterface;
13
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
14
use Clue\React\Buzz\Browser;
15
use Illuminate\Console\Command;
16
use Illuminate\Support\Facades\Cache;
17
use React\Dns\Config\Config as DnsConfig;
18
use React\Dns\Resolver\Factory as DnsFactory;
19
use React\Dns\Resolver\ResolverInterface;
20
use React\EventLoop\Factory as LoopFactory;
21
use React\Socket\Connector;
22
23
class StartWebSocketServer extends Command
24
{
25
    protected $signature = 'websockets:serve {--host=0.0.0.0} {--port=6001} {--debug : Forces the loggers to be enabled and thereby overriding the app.debug config setting } ';
26
27
    protected $description = 'Start the Laravel WebSocket Server';
28
29
    /** @var \React\EventLoop\LoopInterface */
30
    protected $loop;
31
32
    /** @var int */
33
    protected $lastRestart;
34
35
    public function __construct()
36
    {
37
        parent::__construct();
38
39
        $this->loop = LoopFactory::create();
40
    }
41
42
    public function handle()
43
    {
44
        $this
45
            ->configureStatisticsLogger()
46
            ->configureHttpLogger()
47
            ->configureMessageLogger()
48
            ->configureConnectionLogger()
49
            ->configureRestartTimer()
50
            ->registerEchoRoutes()
51
            ->registerCustomRoutes()
52
            ->startWebSocketServer();
53
    }
54
55
    protected function configureStatisticsLogger()
56
    {
57
        $connector = new Connector($this->loop, [
58
            'dns' => $this->getDnsResolver(),
59
            'tls' => [
60
                'verify_peer' => config('app.env') === 'production',
61
                'verify_peer_name' => config('app.env') === 'production',
62
            ],
63
        ]);
64
65
        $browser = new Browser($this->loop, $connector);
66
67
        app()->singleton(StatisticsLoggerInterface::class, function () use ($browser) {
68
            $class = config('websockets.statistics.logger', \BeyondCode\LaravelWebSockets\Statistics\Logger::class);
69
70
            return new $class(app(ChannelManager::class), $browser);
71
        });
72
73
        $this->loop->addPeriodicTimer(config('websockets.statistics.interval_in_seconds'), function () {
74
            StatisticsLogger::save();
75
        });
76
77
        return $this;
78
    }
79
80 View Code Duplication
    protected function configureHttpLogger()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
81
    {
82
        app()->singleton(HttpLogger::class, function () {
83
            return (new HttpLogger($this->output))
84
                ->enable($this->option('debug') ?: config('app.debug'))
85
                ->verbose($this->output->isVerbose());
86
        });
87
88
        return $this;
89
    }
90
91 View Code Duplication
    protected function configureMessageLogger()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
92
    {
93
        app()->singleton(WebsocketsLogger::class, function () {
94
            return (new WebsocketsLogger($this->output))
95
                ->enable($this->option('debug') ?: config('app.debug'))
96
                ->verbose($this->output->isVerbose());
97
        });
98
99
        return $this;
100
    }
101
102 View Code Duplication
    protected function configureConnectionLogger()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
103
    {
104
        app()->bind(ConnectionLogger::class, function () {
105
            return (new ConnectionLogger($this->output))
106
                ->enable(config('app.debug'))
107
                ->verbose($this->output->isVerbose());
108
        });
109
110
        return $this;
111
    }
112
113
    public function configureRestartTimer()
114
    {
115
        $this->lastRestart = $this->getLastRestart();
116
117
        $this->loop->addPeriodicTimer(10, function () {
118
            if ($this->getLastRestart() !== $this->lastRestart) {
119
                $this->loop->stop();
120
            }
121
        });
122
123
        return $this;
124
    }
125
126
    protected function registerEchoRoutes()
127
    {
128
        WebSocketsRouter::echo();
129
130
        return $this;
131
    }
132
133
    protected function registerCustomRoutes()
134
    {
135
        WebSocketsRouter::customRoutes();
136
137
        return $this;
138
    }
139
140
    protected function startWebSocketServer()
141
    {
142
        $this->info("Starting the WebSocket server on port {$this->option('port')}...");
143
144
        $routes = WebSocketsRouter::getRoutes();
145
146
        /* 🛰 Start the server 🛰  */
147
        (new WebSocketServerFactory())
148
            ->setLoop($this->loop)
149
            ->useRoutes($routes)
150
            ->setHost($this->option('host'))
151
            ->setPort($this->option('port'))
152
            ->setConsoleOutput($this->output)
153
            ->createServer()
154
            ->run();
155
    }
156
157
    protected function getDnsResolver(): ResolverInterface
158
    {
159
        if (! config('websockets.statistics.perform_dns_lookup')) {
160
            return new DnsResolver;
161
        }
162
163
        $dnsConfig = DnsConfig::loadSystemConfigBlocking();
164
165
        return (new DnsFactory)->createCached(
166
            $dnsConfig->nameservers
167
                ? reset($dnsConfig->nameservers)
168
                : '1.1.1.1',
169
            $this->loop
170
        );
171
    }
172
173
    protected function getLastRestart()
174
    {
175
        return Cache::get('beyondcode:websockets:restart', 0);
176
    }
177
}
178