From ee280ca6b52305ef5f14a10e7aa7cc260eebed21 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Thu, 7 Sep 2023 19:39:40 +0300 Subject: [PATCH 01/10] Add controller to receive data from dev server --- config/routes.php | 4 ++ src/Controller/DevServerController.php | 71 ++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/Controller/DevServerController.php diff --git a/config/routes.php b/config/routes.php index 7fd5827..e1bc5f8 100644 --- a/config/routes.php +++ b/config/routes.php @@ -12,6 +12,7 @@ use Yiisoft\Yii\Debug\Api\Controller\CommandController; use Yiisoft\Yii\Debug\Api\Controller\ComposerController; use Yiisoft\Yii\Debug\Api\Controller\DebugController; +use Yiisoft\Yii\Debug\Api\Controller\DevServerController; use Yiisoft\Yii\Debug\Api\Controller\GitController; use Yiisoft\Yii\Debug\Api\Controller\InspectController; use Yiisoft\Yii\Debug\Api\Middleware\ResponseDataWrapper; @@ -57,6 +58,9 @@ static function (ResponseFactoryInterface $responseFactory, ValidatorInterface $ Route::get('/event-stream') ->action([DebugController::class, 'eventStream']) ->name('event-stream'), + Route::get('/dev') + ->action([DevServerController::class, 'stream']) + ->name('stream'), ), Group::create('/inspect/api') ->withCors(CorsAllowAll::class) diff --git a/src/Controller/DevServerController.php b/src/Controller/DevServerController.php new file mode 100644 index 0000000..8d55361 --- /dev/null +++ b/src/Controller/DevServerController.php @@ -0,0 +1,71 @@ +createResponse() + ->withHeader('Content-Type', 'text/event-stream') + ->withHeader('Cache-Control', 'no-cache') + ->withHeader('Connection', 'keep-alive') + ->withBody( + new ServerSentEventsStream(function (array &$buffer) use ( + &$hash, + &$retries, + $maxRetries, + ) { + $socket = Connection::create(); + $socket->bind(); + $messages = $socket->read( + fn (string $data) => $data, + fn () => yield 0x001, + ); + foreach ($messages as $message) { + if ($message === 0x001) { + return true; + } + $buffer[] = $message; + + // break the loop if the client aborted the connection (closed the page) + if (connection_aborted()) { + return true; + } + if ($retries++ >= $maxRetries) { + return true; + } + + sleep(1); + return true; + } + }) + ); + } + +} From 28383b09dcbc3e4acf18673b648c053fdc6825e4 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 7 Sep 2023 16:44:43 +0000 Subject: [PATCH 02/10] Apply fixes from StyleCI --- src/Controller/DevServerController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Controller/DevServerController.php b/src/Controller/DevServerController.php index 8d55361..7deea80 100644 --- a/src/Controller/DevServerController.php +++ b/src/Controller/DevServerController.php @@ -67,5 +67,4 @@ public function stream( }) ); } - } From 7adb5ead7d99f6dc8c267ac3281d598ce4f7a8d3 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Mon, 11 Sep 2023 03:26:22 +0700 Subject: [PATCH 03/10] Use generator instead of function argument --- src/Controller/DevServerController.php | 61 +++++++++----------------- src/ServerSentEventsStream.php | 25 +++++------ 2 files changed, 33 insertions(+), 53 deletions(-) diff --git a/src/Controller/DevServerController.php b/src/Controller/DevServerController.php index 7deea80..e36b84c 100644 --- a/src/Controller/DevServerController.php +++ b/src/Controller/DevServerController.php @@ -6,64 +6,45 @@ use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; -use Yiisoft\Aliases\Aliases; -use Yiisoft\DataResponse\DataResponseFactoryInterface; +use Yiisoft\Http\Header; use Yiisoft\Yii\Debug\Api\ServerSentEventsStream; use Yiisoft\Yii\Debug\DevServer\Connection; final class DevServerController { - public function __construct( - private DataResponseFactoryInterface $responseFactory, - private Aliases $aliases, - ) { - } - public function stream( ResponseFactoryInterface $responseFactory ): ResponseInterface { - $maxRetries = 1; - $retries = 0; - if (\function_exists('pcntl_signal')) { \pcntl_signal(\SIGINT, static function (): void { exit(1); }); } + $socket = Connection::create(); + $socket->bind(); + return $responseFactory->createResponse() - ->withHeader('Content-Type', 'text/event-stream') - ->withHeader('Cache-Control', 'no-cache') - ->withHeader('Connection', 'keep-alive') + ->withHeader(Header::CONTENT_TYPE, 'text/event-stream') + ->withHeader(Header::CACHE_CONTROL, 'no-cache') + ->withHeader(Header::CONNECTION, 'keep-alive') ->withBody( - new ServerSentEventsStream(function (array &$buffer) use ( - &$hash, - &$retries, - $maxRetries, - ) { - $socket = Connection::create(); - $socket->bind(); - $messages = $socket->read( - fn (string $data) => $data, - fn () => yield 0x001, - ); - foreach ($messages as $message) { - if ($message === 0x001) { - return true; + new ServerSentEventsStream(function () use ($socket) { + foreach ($socket->read() as $message) { + switch ($message[0]) { + case Connection::TYPE_ERROR: + return ''; + default: + /** + * Break the loop if the client aborted the connection (closed the page) + */ + if (connection_aborted()) { + return $message[1]; + } + yield $message[1]; } - $buffer[] = $message; - - // break the loop if the client aborted the connection (closed the page) - if (connection_aborted()) { - return true; - } - if ($retries++ >= $maxRetries) { - return true; - } - - sleep(1); - return true; } + return ''; }) ); } diff --git a/src/ServerSentEventsStream.php b/src/ServerSentEventsStream.php index 5cecdce..b150ec3 100644 --- a/src/ServerSentEventsStream.php +++ b/src/ServerSentEventsStream.php @@ -5,13 +5,16 @@ namespace Yiisoft\Yii\Debug\Api; use Closure; +use Generator; use Psr\Http\Message\StreamInterface; final class ServerSentEventsStream implements StreamInterface, \Stringable { - public array $buffer = []; private bool $eof = false; + /** + * @param Closure(): Generator $stream + */ public function __construct( private Closure $stream, ) { @@ -77,24 +80,20 @@ public function isReadable(): bool */ public function read(int $length): string { - $continue = ($this->stream)($this->buffer); + foreach (($this->stream)($this) as $message) { + if (empty($message)) { + break; + } - if (!$continue) { - $this->eof = true; + return sprintf("data: %s\n\n", $message); } - - $output = ''; - foreach ($this->buffer as $key => $value) { - unset($this->buffer[$key]); - $output .= sprintf("data: %s\n", $value); - } - $output .= "\n"; - return $output; + $this->eof = true; + return ''; } public function getContents(): string { - return $this->read(1024); + return $this->read(8_388_608); // 8MB } public function getMetadata($key = null): array From 463152d2142cd8abdcac1f4b940131e52750b907 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 16 Sep 2023 16:51:21 +0300 Subject: [PATCH 04/10] Rename dev server -> debug server --- config/routes.php | 4 ++-- .../{DevServerController.php => DebugServerController.php} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/Controller/{DevServerController.php => DebugServerController.php} (95%) diff --git a/config/routes.php b/config/routes.php index e1bc5f8..ff9dc62 100644 --- a/config/routes.php +++ b/config/routes.php @@ -12,7 +12,7 @@ use Yiisoft\Yii\Debug\Api\Controller\CommandController; use Yiisoft\Yii\Debug\Api\Controller\ComposerController; use Yiisoft\Yii\Debug\Api\Controller\DebugController; -use Yiisoft\Yii\Debug\Api\Controller\DevServerController; +use Yiisoft\Yii\Debug\Api\Controller\DebugServerController; use Yiisoft\Yii\Debug\Api\Controller\GitController; use Yiisoft\Yii\Debug\Api\Controller\InspectController; use Yiisoft\Yii\Debug\Api\Middleware\ResponseDataWrapper; @@ -59,7 +59,7 @@ static function (ResponseFactoryInterface $responseFactory, ValidatorInterface $ ->action([DebugController::class, 'eventStream']) ->name('event-stream'), Route::get('/dev') - ->action([DevServerController::class, 'stream']) + ->action([DebugServerController::class, 'stream']) ->name('stream'), ), Group::create('/inspect/api') diff --git a/src/Controller/DevServerController.php b/src/Controller/DebugServerController.php similarity index 95% rename from src/Controller/DevServerController.php rename to src/Controller/DebugServerController.php index e36b84c..f3b44b0 100644 --- a/src/Controller/DevServerController.php +++ b/src/Controller/DebugServerController.php @@ -8,9 +8,9 @@ use Psr\Http\Message\ResponseInterface; use Yiisoft\Http\Header; use Yiisoft\Yii\Debug\Api\ServerSentEventsStream; -use Yiisoft\Yii\Debug\DevServer\Connection; +use Yiisoft\Yii\Debug\DebugServer\Connection; -final class DevServerController +final class DebugServerController { public function stream( ResponseFactoryInterface $responseFactory From ff7876b1202984c2ff39e2bf6e89581e613f7d2e Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 3 Mar 2024 09:17:09 +0700 Subject: [PATCH 05/10] Fix merge conflicts --- config/routes.php | 2 +- src/Inspector/Controller/DebugServerController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/routes.php b/config/routes.php index a0a7344..5a80407 100644 --- a/config/routes.php +++ b/config/routes.php @@ -9,11 +9,11 @@ use Yiisoft\Router\Route; use Yiisoft\Validator\ValidatorInterface; use Yiisoft\Yii\Debug\Api\Debug\Controller\DebugController; -use Yiisoft\Yii\Debug\Api\Debug\Controller\DebugServerController; use Yiisoft\Yii\Debug\Api\Debug\Middleware\ResponseDataWrapper; use Yiisoft\Yii\Debug\Api\Inspector\Controller\CacheController; use Yiisoft\Yii\Debug\Api\Inspector\Controller\CommandController; use Yiisoft\Yii\Debug\Api\Inspector\Controller\ComposerController; +use Yiisoft\Yii\Debug\Api\Inspector\Controller\DebugServerController; use Yiisoft\Yii\Debug\Api\Inspector\Controller\GitController; use Yiisoft\Yii\Debug\Api\Inspector\Controller\InspectController; use Yiisoft\Yii\Middleware\CorsAllowAll; diff --git a/src/Inspector/Controller/DebugServerController.php b/src/Inspector/Controller/DebugServerController.php index f3b44b0..b4782e7 100644 --- a/src/Inspector/Controller/DebugServerController.php +++ b/src/Inspector/Controller/DebugServerController.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Yii\Debug\Api\Controller; +namespace Yiisoft\Yii\Debug\Api\Inspector\Controller; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; From 20765dbbada8dd48997fb24e094ffb09ac0b1872 Mon Sep 17 00:00:00 2001 From: xepozz Date: Sun, 3 Mar 2024 02:22:29 +0000 Subject: [PATCH 06/10] Apply Rector changes (CI) --- src/Inspector/Controller/DebugServerController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Inspector/Controller/DebugServerController.php b/src/Inspector/Controller/DebugServerController.php index b4782e7..2a3adb7 100644 --- a/src/Inspector/Controller/DebugServerController.php +++ b/src/Inspector/Controller/DebugServerController.php @@ -16,7 +16,7 @@ public function stream( ResponseFactoryInterface $responseFactory ): ResponseInterface { if (\function_exists('pcntl_signal')) { - \pcntl_signal(\SIGINT, static function (): void { + \pcntl_signal(\SIGINT, static function (): never { exit(1); }); } From fba53bed511518fbbebc77761dc77caa37c14f93 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 7 Jul 2024 07:37:06 +0300 Subject: [PATCH 07/10] Use consts --- src/Debug/Controller/DebugController.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Debug/Controller/DebugController.php b/src/Debug/Controller/DebugController.php index 40ce24f..0dac06d 100644 --- a/src/Debug/Controller/DebugController.php +++ b/src/Debug/Controller/DebugController.php @@ -4,6 +4,7 @@ namespace Yiisoft\Yii\Debug\Api\Debug\Controller; +use OpenApi\Attributes as OA; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; @@ -12,6 +13,7 @@ use Yiisoft\Assets\AssetPublisherInterface; use Yiisoft\DataResponse\DataResponse; use Yiisoft\DataResponse\DataResponseFactoryInterface; +use Yiisoft\Http\Header; use Yiisoft\Router\CurrentRoute; use Yiisoft\Yii\Debug\Api\Debug\Exception\NotFoundException; use Yiisoft\Yii\Debug\Api\Debug\Exception\PackageNotInstalledException; @@ -21,7 +23,6 @@ use Yiisoft\Yii\Debug\Api\ServerSentEventsStream; use Yiisoft\Yii\Debug\Storage\StorageInterface; use Yiisoft\Yii\View\ViewRenderer; -use OpenApi\Attributes as OA; /** * Debug controller provides endpoints that expose information about requests processed that debugger collected. @@ -323,9 +324,9 @@ public function eventStream( $retries = 0; return $responseFactory->createResponse() - ->withHeader('Content-Type', 'text/event-stream') - ->withHeader('Cache-Control', 'no-cache') - ->withHeader('Connection', 'keep-alive') + ->withHeader(Header::CONTENT_TYPE, 'text/event-stream') + ->withHeader(Header::CACHE_CONTROL, 'no-cache') + ->withHeader(Header::CONNECTION, 'keep-alive') ->withBody( new ServerSentEventsStream(function (array &$buffer) use ( $compareFunction, From 66aefb3136f42ae78aa41ae3dcf72b5934f8ab22 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 7 Jul 2024 07:37:25 +0300 Subject: [PATCH 08/10] Release if connection is aborted --- src/Inspector/Controller/DebugServerController.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Inspector/Controller/DebugServerController.php b/src/Inspector/Controller/DebugServerController.php index 2a3adb7..8bd9216 100644 --- a/src/Inspector/Controller/DebugServerController.php +++ b/src/Inspector/Controller/DebugServerController.php @@ -34,13 +34,16 @@ public function stream( switch ($message[0]) { case Connection::TYPE_ERROR: return ''; - default: + case Connection::TYPE_RELEASE: /** * Break the loop if the client aborted the connection (closed the page) */ if (connection_aborted()) { - return $message[1]; + return ''; } + break; + case Connection::TYPE_RESULT: + yield $message[1]; } } From 23b2d1936f57a0dc596ed699f0205c7114aaa779 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 7 Jul 2024 07:37:33 +0300 Subject: [PATCH 09/10] Fix stream --- src/ServerSentEventsStream.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ServerSentEventsStream.php b/src/ServerSentEventsStream.php index 37212d7..a772945 100644 --- a/src/ServerSentEventsStream.php +++ b/src/ServerSentEventsStream.php @@ -30,9 +30,9 @@ public function detach(): void $this->eof = true; } - public function getSize(): int + public function getSize(): ?int { - return 0; + return null; } public function tell(): int From 3ab00db0edc6872f4ce3ae744b3bfeedb3885419 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 12 Jul 2025 09:29:23 +0000 Subject: [PATCH 10/10] Apply fixes from StyleCI --- config/params.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/params.php b/config/params.php index 9630fc8..5351837 100644 --- a/config/params.php +++ b/config/params.php @@ -9,7 +9,7 @@ use Yiisoft\Yii\Debug\Api\Inspector\Command\PsalmCommand; $testCommands = []; -if (class_exists(\PHPUnit\Framework\Test::class)) { +if (class_exists(PHPUnit\Framework\Test::class)) { $testCommands[PHPUnitCommand::COMMAND_NAME] = PHPUnitCommand::class; } if (class_exists(Extension::class)) {