@@ -26,7 +26,7 @@ class StartServer extends Command
26
26
{--disable-statistics : Disable the statistics tracking.}
27
27
{--statistics-interval= : The amount of seconds to tick between statistics saving.}
28
28
{--debug : Forces the loggers to be enabled and thereby overriding the APP_DEBUG setting.}
29
- {--test : Prepare the server, but do not start it .}
29
+ {--loop : Programatically inject the loop .}
30
30
' ;
31
31
32
32
/**
@@ -79,6 +79,8 @@ public function handle()
79
79
80
80
$ this ->configureRoutes ();
81
81
82
+ $ this ->configurePcntlSignal ();
83
+
82
84
$ this ->startServer ();
83
85
}
84
86
@@ -156,6 +158,31 @@ protected function configureRoutes()
156
158
WebSocketRouter::routes ();
157
159
}
158
160
161
+ /**
162
+ * Configure the PCNTL signals for soft shutdown.
163
+ *
164
+ * @return void
165
+ */
166
+ protected function configurePcntlSignal ()
167
+ {
168
+ // When the process receives a SIGTERM or a SIGINT
169
+ // signal, it should mark the server as unavailable
170
+ // to receive new connections, close the current connections,
171
+ // then stopping the loop.
172
+
173
+ $ this ->loop ->addSignal (SIGTERM , function () {
174
+ $ this ->line ('Closing existing connections... ' );
175
+
176
+ $ this ->triggerSoftShutdown ();
177
+ });
178
+
179
+ $ this ->loop ->addSignal (SIGINT , function () {
180
+ $ this ->line ('Closing existing connections... ' );
181
+
182
+ $ this ->triggerSoftShutdown ();
183
+ });
184
+ }
185
+
159
186
/**
160
187
* Configure the HTTP logger class.
161
188
*
@@ -209,14 +236,6 @@ protected function startServer()
209
236
210
237
$ this ->buildServer ();
211
238
212
- // For testing, just boot up the server, run it
213
- // but exit after the next tick.
214
- if ($ this ->option ('test ' )) {
215
- $ this ->loop ->futureTick (function () {
216
- $ this ->loop ->stop ();
217
- });
218
- }
219
-
220
239
$ this ->server ->run ();
221
240
}
222
241
@@ -231,6 +250,10 @@ protected function buildServer()
231
250
$ this ->option ('host ' ), $ this ->option ('port ' )
232
251
);
233
252
253
+ if ($ loop = $ this ->option ('loop ' )) {
254
+ $ this ->loop = $ loop ;
255
+ }
256
+
234
257
$ this ->server = $ this ->server
235
258
->setLoop ($ this ->loop )
236
259
->withRoutes (WebSocketRouter::getRoutes ())
@@ -249,4 +272,29 @@ protected function getLastRestart()
249
272
'beyondcode:websockets:restart ' , 0
250
273
);
251
274
}
275
+
276
+ /**
277
+ * Trigger a soft shutdown for the process.
278
+ *
279
+ * @return void
280
+ */
281
+ protected function triggerSoftShutdown ()
282
+ {
283
+ $ channelManager = $ this ->laravel ->make (ChannelManager::class);
284
+
285
+ // Close the new connections allowance on this server.
286
+ $ channelManager ->declineNewConnections ();
287
+
288
+ // Get all local connections and close them. They will
289
+ // be automatically be unsubscribed from all channels.
290
+ $ channelManager ->getLocalConnections ()
291
+ ->then (function ($ connections ) use ($ channelManager ) {
292
+ foreach ($ connections as $ connection ) {
293
+ $ connection ->close ();
294
+ }
295
+ })
296
+ ->then (function () {
297
+ $ this ->loop ->stop ();
298
+ });
299
+ }
252
300
}
0 commit comments