A steer
This commit is contained in:
parent
636d9eccb8
commit
a2a5524637
|
|
@ -74,6 +74,13 @@ class StartServer extends Command
|
||||||
*/
|
*/
|
||||||
protected $restartSoftShutdown = false;
|
protected $restartSoftShutdown = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last steer signal timestamp.
|
||||||
|
*
|
||||||
|
* @var int|null
|
||||||
|
*/
|
||||||
|
protected $lastSteer = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the command.
|
* Initialize the command.
|
||||||
*
|
*
|
||||||
|
|
@ -148,6 +155,10 @@ class StartServer extends Command
|
||||||
$this->configureRestartTimer();
|
$this->configureRestartTimer();
|
||||||
\Log::channel('websocket')->debug('Restart timer configured');
|
\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...');
|
\Log::channel('websocket')->debug('Configuring routes...');
|
||||||
$this->configureRoutes();
|
$this->configureRoutes();
|
||||||
\Log::channel('websocket')->debug('Routes configured');
|
\Log::channel('websocket')->debug('Routes configured');
|
||||||
|
|
@ -290,6 +301,84 @@ class StartServer extends Command
|
||||||
\Log::channel('websocket')->debug('WebSocket routes registered');
|
\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.
|
* 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([
|
$this->commands([
|
||||||
Console\Commands\StartServer::class,
|
Console\Commands\StartServer::class,
|
||||||
Console\Commands\RestartServer::class,
|
Console\Commands\RestartServer::class,
|
||||||
|
Console\Commands\SteerServer::class,
|
||||||
Console\Commands\CleanStatistics::class,
|
Console\Commands\CleanStatistics::class,
|
||||||
Console\Commands\FlushCollectedStatistics::class,
|
Console\Commands\FlushCollectedStatistics::class,
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue