A steer
This commit is contained in:
parent
636d9eccb8
commit
a2a5524637
|
|
@ -74,6 +74,13 @@ class StartServer extends Command
|
|||
*/
|
||||
protected $restartSoftShutdown = false;
|
||||
|
||||
/**
|
||||
* The last steer signal timestamp.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
protected $lastSteer = null;
|
||||
|
||||
/**
|
||||
* Initialize the command.
|
||||
*
|
||||
|
|
@ -148,6 +155,10 @@ class StartServer extends Command
|
|||
$this->configureRestartTimer();
|
||||
\Log::channel('websocket')->debug('Restart timer configured');
|
||||
|
||||
\Log::channel('websocket')->debug('Configuring steer timer...');
|
||||
$this->configureSteerTimer();
|
||||
\Log::channel('websocket')->debug('Steer timer configured');
|
||||
|
||||
\Log::channel('websocket')->debug('Configuring routes...');
|
||||
$this->configureRoutes();
|
||||
\Log::channel('websocket')->debug('Routes configured');
|
||||
|
|
@ -290,6 +301,84 @@ class StartServer extends Command
|
|||
\Log::channel('websocket')->debug('WebSocket routes registered');
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the timer that polls for steer signals (cache:clear, etc.).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureSteerTimer(): void
|
||||
{
|
||||
$steerData = Cache::store('file')->get('blax:websockets:steer');
|
||||
$this->lastSteer = $steerData['time'] ?? null;
|
||||
|
||||
\Log::channel('websocket')->debug('Steer timer configured', [
|
||||
'initial_steer_time' => $this->lastSteer,
|
||||
]);
|
||||
|
||||
$this->loop->addPeriodicTimer(5, function () {
|
||||
$steerData = Cache::store('file')->get('blax:websockets:steer');
|
||||
$currentSteer = $steerData['time'] ?? null;
|
||||
|
||||
if ($currentSteer !== null && $currentSteer !== $this->lastSteer) {
|
||||
$action = $steerData['action'] ?? null;
|
||||
$this->lastSteer = $currentSteer;
|
||||
|
||||
\Log::channel('websocket')->info("Steer signal received: {$action}");
|
||||
$this->handleSteerAction($action);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a steer action received via the cache signal.
|
||||
*/
|
||||
protected function handleSteerAction(?string $action): void
|
||||
{
|
||||
switch ($action) {
|
||||
case 'cache:clear':
|
||||
$this->steerCacheClear();
|
||||
break;
|
||||
|
||||
case 'restart':
|
||||
$this->restartSoftShutdown = false;
|
||||
$this->triggerShutdown(true);
|
||||
break;
|
||||
|
||||
case 'restart:soft':
|
||||
$this->restartSoftShutdown = true;
|
||||
$this->triggerShutdown(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
\Log::channel('websocket')->warning("Unknown steer action: {$action}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear OPcache and the controller resolution cache so the running
|
||||
* server picks up new code from disk without a full restart.
|
||||
*/
|
||||
protected function steerCacheClear(): void
|
||||
{
|
||||
$cleared = [];
|
||||
|
||||
// 1. Reset OPcache — forces PHP to recompile files from disk
|
||||
if (function_exists('opcache_reset')) {
|
||||
opcache_reset();
|
||||
$cleared[] = 'opcache';
|
||||
}
|
||||
|
||||
// 2. Clear controller resolver cache so new/changed controllers are discovered
|
||||
if (class_exists(\BlaxSoftware\LaravelWebSockets\Websocket\ControllerResolver::class)) {
|
||||
\BlaxSoftware\LaravelWebSockets\Websocket\ControllerResolver::clearCache();
|
||||
\BlaxSoftware\LaravelWebSockets\Websocket\ControllerResolver::preload();
|
||||
$cleared[] = 'controllers';
|
||||
}
|
||||
|
||||
\Log::channel('websocket')->info('Steer cache:clear executed', ['cleared' => $cleared]);
|
||||
$this->line('Cache cleared: ' . implode(', ', $cleared));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the PCNTL signals for soft shutdown.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace BlaxSoftware\LaravelWebSockets\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
|
||||
class SteerServer extends Command
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
protected $signature = 'websocket:steer
|
||||
{action : The action to send (cache:clear, restart, restart:soft)}
|
||||
{--cache-driver=file : The cache driver to use for signaling.}';
|
||||
|
||||
protected $description = 'Send a steering command to the running WebSocket server.';
|
||||
|
||||
/** @var array<string, string> */
|
||||
protected array $actions = [
|
||||
'cache:clear' => 'Clear OPcache and controller resolution cache (picks up new code without full restart)',
|
||||
'restart' => 'Hard-restart the server (stops loop, supervisord restarts the process)',
|
||||
'restart:soft' => 'Soft-restart the server (gracefully close connections first)',
|
||||
];
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$action = $this->argument('action');
|
||||
|
||||
if (! array_key_exists($action, $this->actions)) {
|
||||
$this->error("Unknown action: {$action}");
|
||||
$this->line('');
|
||||
$this->info('Available actions:');
|
||||
foreach ($this->actions as $name => $desc) {
|
||||
$this->line(" <comment>{$name}</comment> {$desc}");
|
||||
}
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$store = $this->option('cache-driver') ?: 'file';
|
||||
|
||||
Cache::store($store)->forever('blax:websockets:steer', [
|
||||
'action' => $action,
|
||||
'time' => $this->currentTime(),
|
||||
]);
|
||||
|
||||
\Log::channel('websocket')->info("WebSocket steer signal sent: {$action}");
|
||||
$this->info("Sent '{$action}' signal to the WebSocket server.");
|
||||
$this->line("<comment>{$this->actions[$action]}</comment>");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
@ -202,6 +202,7 @@ class WebSocketsServiceProvider extends ServiceProvider
|
|||
$this->commands([
|
||||
Console\Commands\StartServer::class,
|
||||
Console\Commands\RestartServer::class,
|
||||
Console\Commands\SteerServer::class,
|
||||
Console\Commands\CleanStatistics::class,
|
||||
Console\Commands\FlushCollectedStatistics::class,
|
||||
]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue