From ffbacee7755cb26bd92f92cf811dda13dfde167a Mon Sep 17 00:00:00 2001 From: cclilshy Date: Sat, 25 Jan 2025 23:43:08 +0800 Subject: [PATCH] Optimize terminal layout --- src/.env.example | 4 +- src/Client.php | 47 +++++++----------- src/Config/ripple.php | 2 +- src/Octane/Bin/ripple-server.bin.php | 57 ++++++++++++---------- src/Octane/Bin/ripple-ware.bin.php | 16 ++---- src/Octane/Commands/RippleStartCommand.php | 6 +-- src/Util.php | 52 ++++++++++++++++++++ src/Virtual/Virtual.php | 40 ++++++++++++--- src/Virtual/server.bin.php | 44 +++++++++++++---- 9 files changed, 179 insertions(+), 89 deletions(-) create mode 100644 src/Util.php diff --git a/src/.env.example b/src/.env.example index 43e6514..063f3f8 100755 --- a/src/.env.example +++ b/src/.env.example @@ -1,3 +1,3 @@ -RIP_HTTP_LISTEN=http://127.0.0.1:8008 +RIP_HTTP_LISTEN=http://127.0.0.1:8000 RIP_HTTP_WORKERS=1 -RIP_HTTP_RELOAD=1 +RIP_WATCH=0 diff --git a/src/Client.php b/src/Client.php index 11c43c0..e20d9c3 100755 --- a/src/Client.php +++ b/src/Client.php @@ -12,12 +12,12 @@ namespace Laravel\Ripple; +use Illuminate\Support\Facades\Config; use Laravel\Ripple\Virtual\Virtual; use Revolt\EventLoop\UnsupportedFeatureException; use Ripple\Channel\Channel; use Ripple\File\Lock; use Ripple\Utils\Output; -use Throwable; use function base_path; use function cli_set_process_title; @@ -27,6 +27,7 @@ use function Co\wait; use function config_path; use function file_exists; +use function fwrite; use function shell_exec; use function sprintf; use function storage_path; @@ -35,21 +36,22 @@ use const SIGINT; use const SIGQUIT; use const SIGTERM; +use const STDOUT; class Client { /*** @var \Laravel\Ripple\Inspector */ public readonly Inspector $inspector; - /*** @var \Laravel\Ripple\Virtual\Virtual */ - public readonly Virtual $virtual; - /*** @var \Ripple\Channel\Channel */ public readonly Channel $channel; /*** @var \Ripple\File\Lock */ public readonly Lock $lock; + /*** @var \Laravel\Ripple\Virtual\Virtual */ + public Virtual $virtual; + /*** @var bool */ public bool $owner = false; @@ -96,8 +98,10 @@ public function start(bool $daemon = false): void $this->owner = true; $this->lock->exclusion(false); $this->virtual = new Virtual(__DIR__ . '/Virtual/server.bin.php'); - $this->virtual->launch(); - $this->virtual->session->onMessage = static fn (string $content) => Output::writeln($content); + $this->virtual->launch([ + 'RIP_WATCH' => Config::get('ripple.RIP_WATCH') + ]); + $this->virtual->session->onMessage = static fn (string $content) => fwrite(STDOUT, $content); $this->virtual->session->onErrorMessage = static fn (string $content) => Output::error($content); $this->channel = channel(base_path(), true); @@ -107,37 +111,22 @@ public function start(bool $daemon = false): void $command = $this->channel->receive(); switch ($command) { case 'stop': - $this->virtual->channel->send('stop'); - try { - \Co\sleep(0.1); - if ($this->virtual->session->getStatus('running')) { - \Co\sleep(1); - $this->virtual->session->inputSignal(SIGINT); - } - } catch (Throwable) { - } + $this->virtual->stop(); exit(0); break; case 'reload': - $oldVirtual = $this->virtual; + fwrite(STDOUT, "\033c"); + $oldVirtual = $this->virtual; $virtual = new Virtual(__DIR__ . '/Virtual/server.bin.php'); - $virtual->launch(); + $virtual->launch([ + 'RIP_WATCH' => Config::get('ripple.RIP_WATCH') + ]); $this->virtual = $virtual; - $this->virtual->session->onMessage = static fn (string $content) => Output::writeln($content); + $this->virtual->session->onMessage = static fn (string $content) => fwrite(STDOUT, $content); $this->virtual->session->onErrorMessage = static fn (string $content) => Output::error($content); - $oldVirtual->channel->send('stop'); - - try { - \Co\sleep(0.1); - if ($oldVirtual->session->getStatus('running')) { - \Co\sleep(1); - $oldVirtual->session->inputSignal(SIGINT); - } - } catch (Throwable) { - } - + $oldVirtual->stop(); break; } } diff --git a/src/Config/ripple.php b/src/Config/ripple.php index 878bc21..83fa80a 100755 --- a/src/Config/ripple.php +++ b/src/Config/ripple.php @@ -16,5 +16,5 @@ return [ 'HTTP_LISTEN' => Env::get('RIP_HTTP_LISTEN', 'http://127.0.0.1:8008'), 'HTTP_WORKERS' => Env::get('RIP_HTTP_WORKERS', 1), - 'HTTP_RELOAD' => Env::get('RIP_HTTP_RELOAD', 1) + 'HTTP_WATCH' => Env::get('RIP_WATCH', 0) ]; diff --git a/src/Octane/Bin/ripple-server.bin.php b/src/Octane/Bin/ripple-server.bin.php index 13a8f06..5f2d1a9 100755 --- a/src/Octane/Bin/ripple-server.bin.php +++ b/src/Octane/Bin/ripple-server.bin.php @@ -15,9 +15,11 @@ use Illuminate\Contracts\Container\BindingResolutionException; use Laravel\Octane\ApplicationFactory; use Laravel\Octane\RequestContext; +use Laravel\Octane\Worker; use Laravel\Ripple\Factory; use Laravel\Ripple\HttpWorker; use Laravel\Ripple\Octane\RippleClient; +use Laravel\Ripple\Util; use Revolt\EventLoop\UnsupportedFeatureException; use Ripple\Http\Server\Request; use Ripple\Utils\Output; @@ -34,12 +36,12 @@ \define("RIP_HOST", \getenv('RIP_HOST')); \define("RIP_PORT", \getenv('RIP_PORT')); \define("RIP_WORKERS", \getenv('RIP_WORKERS')); -\define("RIP_RELOAD", \getenv('RIP_RELOAD')); +\define("RIP_WATCH", \getenv('RIP_WATCH')); require RIP_PROJECT_PATH . '/vendor/autoload.php'; /*** Octane part */ -$octaneWorker = new \Laravel\Octane\Worker( +$octaneWorker = new Worker( new ApplicationFactory(RIP_PROJECT_PATH), $octaneClient = new RippleClient() ); @@ -53,7 +55,7 @@ $application, 'http://' . RIP_HOST . ':' . RIP_PORT, \intval(RIP_WORKERS), - \boolval(RIP_RELOAD) + \boolval(RIP_WATCH) ); $application->singleton(Manager::class, static fn () => $manager); $application->singleton(HttpWorker::class, static fn () => $httpWorker); @@ -67,18 +69,21 @@ ...$octaneClient->marshalRequest(new RequestContext(['rippleRequest' => $rippleRequest])) ); }); -$manager->addWorker($httpWorker); +$manager->add($httpWorker); /*** Hot reload part */ $projectChannel = channel(RIP_PROJECT_PATH); $includedFiles = \get_included_files(); $hotReload = static function (string $file) use ($manager, $includedFiles, $projectChannel) { if (\in_array($file, $includedFiles, true)) { + \fwrite(\STDOUT, "\033c"); $projectChannel->send('reload'); } else { $manager->reload(); $date = \date('Y-m-d H:i:s'); - \is_file($file) && Output::writeln("[{$date}] {$file} has been modified"); + \is_file($file) + && ($file = Util::getRelativePath($file, RIP_PROJECT_PATH)) + && Output::writeln("[{$date}] {$file} has been modified"); } }; @@ -86,41 +91,41 @@ $hotReloadWatch->onModify = $hotReload; $hotReloadWatch->onTouch = $hotReload; $hotReloadWatch->onRemove = $hotReload; -if (\boolval(RIP_RELOAD)) { +if (\boolval(RIP_WATCH)) { $hotReloadWatch->run(); } /*** Guardian part*/ async(static function () use ($manager) { $channel = channel(RIP_VIRTUAL_ID, true); - try { - onSignal(\SIGINT, function () use ($manager) { - $manager->stop(); - exit(0); - }); - - onSignal(\SIGTERM, function () use ($manager) { - $manager->stop(); - exit(0); - }); - - onSignal(\SIGQUIT, function () use ($manager) { - $manager->stop(); - exit(0); - }); - } catch (UnsupportedFeatureException) { - Output::warning('Failed to register signal handler'); - } - while (1) { $control = $channel->receive(); if ($control === 'stop') { - $manager->stop(); + $manager->terminate(); exit(0); } } }); +try { + onSignal(\SIGINT, function () use ($manager) { + $manager->terminate(); + exit(0); + }); + + onSignal(\SIGTERM, function () use ($manager) { + $manager->terminate(); + exit(0); + }); + + onSignal(\SIGQUIT, function () use ($manager) { + $manager->terminate(); + exit(0); + }); +} catch (UnsupportedFeatureException) { + Output::warning('Failed to register signal handler'); +} + /*** start */ Output::info("[laravel-ripple]", 'started'); $manager->run(); diff --git a/src/Octane/Bin/ripple-ware.bin.php b/src/Octane/Bin/ripple-ware.bin.php index 86e0f38..6188c3d 100755 --- a/src/Octane/Bin/ripple-ware.bin.php +++ b/src/Octane/Bin/ripple-ware.bin.php @@ -51,29 +51,23 @@ $virtual = new Virtual($imagePath); $virtual->launch(); -$virtual->session->onMessage = static fn (string $content) => Output::writeln($content); +$virtual->session->onMessage = static fn (string $content) => \fwrite(\STDOUT, $content); $virtual->session->onErrorMessage = static fn (string $content) => Output::error($content); $virtualStop = static function () use (&$virtual) { - $virtual->channel->send('stop'); - try { - \Co\sleep(0.1); - if ($virtual->session->getStatus('running')) { - \Co\sleep(1); - $virtual->session->inputSignal(\SIGINT); - } - } catch (Throwable) { - } + $virtual->stop(); exit(0); }; $virtualReboot = static function () use (&$virtual, $imagePath) { + \fwrite(\STDOUT, "\033c"); + $oldVirtual = $virtual; $_virtual = new Virtual($imagePath); $_virtual->launch(); $oldVirtual->channel->send('stop'); $virtual = $_virtual; - $virtual->session->onMessage = static fn (string $content) => Output::writeln($content); + $virtual->session->onMessage = static fn (string $content) => \fwrite(\STDOUT, $content); $virtual->session->onErrorMessage = static fn (string $content) => Output::error($content); }; diff --git a/src/Octane/Commands/RippleStartCommand.php b/src/Octane/Commands/RippleStartCommand.php index 5596e4e..1e4ea2f 100755 --- a/src/Octane/Commands/RippleStartCommand.php +++ b/src/Octane/Commands/RippleStartCommand.php @@ -88,10 +88,10 @@ public function handle(RippleServerProcessInspector $inspector): int 'RIP_PROJECT_PATH' => base_path(), 'RIP_BIN_WORKING_PATH' => $binPath, 'APP_BASE_PATH' => base_path(), - 'RIP_HOST' => $this->option('host') ?? '127.0.0.1', - 'RIP_PORT' => $this->option('port') ?? 8000, + 'RIP_HOST' => $this->getHost(), + 'RIP_PORT' => $this->getPort(), 'RIP_WORKERS' => $workers, - 'RIP_RELOAD' => $watch ?? 0 + 'RIP_WATCH' => $watch ?? 0 ] ); $process->start(); diff --git a/src/Util.php b/src/Util.php new file mode 100644 index 0000000..f63cf0f --- /dev/null +++ b/src/Util.php @@ -0,0 +1,52 @@ +id); - foreach (getenv() as $key => $value) { + foreach (array_merge(getenv(), $envs) as $key => $value) { putenv("{$key}={$value}"); } - $session = proc(PHP_BINARY); - $session->write(file_get_contents($this->virtualPath)); - $session->inputEot(); + $launch = fn () => proc([PHP_BINARY, $this->virtualPath]); + + $session = $launch(); + $session->onClose = function () use ($launch, $session) { + unset($session->onClose); + $this->session = $launch(); + }; return $this->session = $session; } + /** + * @return void + */ + public function stop(): void + { + unset($this->session->onClose); + $this->channel->send('stop'); + try { + \Co\sleep(0.1); + if ($this->session->getStatus('running')) { + \Co\sleep(1); + $this->session->inputSignal(SIGINT); + } + } catch (Throwable) { + } + } + /** * */ diff --git a/src/Virtual/server.bin.php b/src/Virtual/server.bin.php index 953a8cf..c2de54b 100755 --- a/src/Virtual/server.bin.php +++ b/src/Virtual/server.bin.php @@ -15,8 +15,10 @@ use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Foundation\Console\Kernel; use Illuminate\Support\Facades\Config; +use Laravel\Ripple\Coroutine\ContextManager; use Laravel\Ripple\Factory; use Laravel\Ripple\HttpWorker; +use Laravel\Ripple\Util; use Revolt\EventLoop\UnsupportedFeatureException; use Ripple\Utils\Output; use Ripple\Worker\Manager; @@ -29,9 +31,25 @@ \cli_set_process_title('laravel-virtual'); \define("RIP_PROJECT_PATH", \realpath(\getenv('RIP_PROJECT_PATH'))); \define("RIP_VIRTUAL_ID", \getenv('RIP_VIRTUAL_ID')); +\define("RIP_WATCH", true); + +if (!\function_exists('app')) { + /** + * @param string|null $abstract + * @param array $parameters + * + * @return mixed + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + function app(string $abstract = null, array $parameters = []): mixed + { + return ContextManager::app($abstract, $parameters); + } +} + require RIP_PROJECT_PATH . '/vendor/autoload.php'; -/*** loadDeferredProviders */ +/*** LoadDeferredProviders */ try { $application = Factory::createApplication(); $kernel = $application->make(Kernel::class); @@ -44,11 +62,11 @@ exit(1); } -$manager->addWorker(new HttpWorker( +$manager->add(new HttpWorker( $application, \strval(Config::get('ripple.HTTP_LISTEN', 'http://127.0.0.1:8008')), \intval(Config::get('ripple.HTTP_WORKER_COUNT', 1)), - \boolval(Config::get('ripple.HTTP_RELOAD', true)) + \boolval(RIP_WATCH) )); /*** Hot reload part */ @@ -60,31 +78,35 @@ } else { $manager->reload(); $date = \date('Y-m-d H:i:s'); - \is_file($file) && Output::writeln("[{$date}] {$file} has been modified"); + \is_file($file) + && ($file = Util::getRelativePath($file, RIP_PROJECT_PATH)) + && Output::writeln("[{$date}] {$file} has been modified"); } }; $hotReloadWatch = Factory::createMonitor(); $hotReloadWatch->onModify = $hotReload; $hotReloadWatch->onTouch = $hotReload; $hotReloadWatch->onRemove = $hotReload; -$hotReloadWatch->run(); +if (\boolval(RIP_WATCH)) { + $hotReloadWatch->run(); +} /*** Guardian part*/ async(function () use ($manager) { $channel = channel(RIP_VIRTUAL_ID, true); try { onSignal(\SIGINT, function () use ($manager) { - $manager->stop(); + $manager->terminate(); exit(0); }); onSignal(\SIGTERM, function () use ($manager) { - $manager->stop(); + $manager->terminate(); exit(0); }); onSignal(\SIGQUIT, function () use ($manager) { - $manager->stop(); + $manager->terminate(); exit(0); }); } catch (UnsupportedFeatureException) { @@ -94,9 +116,13 @@ while (1) { $control = $channel->receive(); if ($control === 'stop') { - $manager->stop(); + $manager->terminate(); exit(0); } + + if ($control === 'reload') { + $manager->reload(); + } } });