Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .docker/velox.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,4 @@ repository = "tcp"
[github.plugins.smtp-server]
ref = "2.0.0"
owner = "buggregator"
repository = "smtp-server"

[github.plugins.var-dumper-server]
ref = "1.0.0"
owner = "buggregator"
repository = "var-dumper-server"
repository = "smtp-server"
37 changes: 23 additions & 14 deletions .rr-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,32 @@ server:
command: "php app.php register:modules"

logs:
# Logging mode can be "development", "production" or "raw".
# Do not forget to change this value for production environment.
mode: ${RR_LOG_MODE:-production}
# Encoding format can be "console" or "json" (last is preferred for production usage).
encoding: ${RR_LOG_ENCODING:-json}
# Logging level can be "panic", "error", "warn", "info", "debug".
level: ${RR_LOG_LEVEL:-warn}
channels:
http:
# HTTP plugin logging level can be "panic", "error", "warn", "info", "debug".
level: ${RR_LOG_HTTP_LEVEL:-warn}
tcp:
# TCP plugin logging level can be "panic", "error", "warn", "info", "debug".
level: ${RR_LOG_TCP_LEVEL:-warn}
jobs:
# JOBS plugin logging level can be "panic", "error", "warn", "info", "debug".
level: ${RR_LOG_JOBS_LEVEL:-warn}
centrifuge:
# Centrifuge plugin logging level can be "panic", "error", "warn", "info", "debug".
level: ${RR_LOG_CENTRIFUGE_LEVEL:-warn}
server:
# Server logging level can be "panic", "error", "warn", "info", "debug".
level: ${RR_LOG_SERVER_LEVEL:-warn}
service:
# Service logging level can be "panic", "error", "warn", "info", "debug".
level: ${RR_LOG_SERVICE_LEVEL:-warn}
smtp:
level: ${RR_LOG_SMTP_LEVEL:-warn}
var-dumper:
level: ${RR_LOG_VAR_DUMPER_LEVEL:-warn}

http:
address: 127.0.0.1:8082
Expand All @@ -51,11 +57,20 @@ http:
tcp:
servers:
monolog:
# Address to listen.
addr: ${RR_TCP_MONOLOG_ADDR:-:9913}
delimiter: "\n"
var-dumper:
# Address to listen.
addr: ${RR_TCP_VAR_DUMPER_ADDR:-:9912}
delimiter: "\n"
# Chunks that RR uses to read the data. In bytes.
# If you expect big payloads on a TCP server, to reduce `read` syscalls,
# would be a good practice to use a fairly big enough buffer.
# Default: 1024 * 1024 * 50 (50MB)
read_buf_size: ${RR_TCP_READ_BUF_SIZE:-50485760}
pool:
num_workers: ${RR_TCP_NUM_WORKERS:-1}
num_workers: ${RR_TCP_NUM_WORKERS:-2}

kv:
local:
Expand All @@ -64,9 +79,9 @@ kv:

jobs:
consume:
- events
- smtp
pipelines:
events:
smtp:
driver: memory
config:
priority: 10
Expand All @@ -78,13 +93,7 @@ smtp:
addr: ${RR_SMTP_ADDR:-:1025}
hostname: "buggregator.local"
jobs:
pipeline: events

var-dumper:
addr: ${RR_VAR_DUMPER_ADDR:-:9912}
max_message_size: ${RR_TCP_READ_BUF_SIZE:-50485760}
jobs:
pipeline: events
pipeline: smtp

service:
nginx:
Expand Down
2 changes: 0 additions & 2 deletions app/config/queue.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
declare(strict_types=1);

use Modules\Smtp\Interfaces\Jobs\EmailHandler;
use Modules\VarDumper\Interfaces\Jobs\DumpHandler;
use Modules\Webhooks\Interfaces\Job\WebhookHandler;
use Spiral\Queue\Driver\SyncDriver;
use Spiral\RoadRunner\Jobs\Queue\MemoryCreateInfo;
Expand Down Expand Up @@ -40,7 +39,6 @@
'registry' => [
'handlers' => [
'smtp.email' => EmailHandler::class,
'vardumper.dump' => DumpHandler::class,
],
'serializers' => [
WebhookHandler::class => 'symfony-json',
Expand Down
2 changes: 2 additions & 0 deletions app/config/tcp.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
declare(strict_types=1);

use App\Application\TCP\ExceptionHandlerInterceptor;
use Modules\VarDumper\Interfaces\TCP\Service as VarDumperService;
use Modules\Monolog\Interfaces\TCP\Service as MonologService;

return [
'services' => [
'var-dumper' => VarDumperService::class,
'monolog' => MonologService::class,
],

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Modules\VarDumper\Interfaces\Jobs;
namespace Modules\VarDumper\Interfaces\TCP;

use App\Application\Commands\HandleReceivedEvent;
use Modules\VarDumper\Application\Dump\BodyInterface;
Expand All @@ -12,32 +12,41 @@
use Modules\VarDumper\Application\Dump\MessageParser;
use Modules\VarDumper\Application\Dump\ParsedPayload;
use Modules\VarDumper\Application\Dump\PrimitiveBody;
use Spiral\Core\InvokerInterface;
use Spiral\Cqrs\CommandBusInterface;
use Spiral\Queue\JobHandler;
use Spiral\RoadRunner\Tcp\Request;
use Spiral\RoadRunner\Tcp\TcpEvent;
use Spiral\RoadRunnerBridge\Tcp\Response\ContinueRead;
use Spiral\RoadRunnerBridge\Tcp\Response\ResponseInterface;
use Spiral\RoadRunnerBridge\Tcp\Service\ServiceInterface;
use Symfony\Component\VarDumper\Cloner\Data;

final class DumpHandler extends JobHandler
final readonly class Service implements ServiceInterface
{
public function __construct(
private readonly CommandBusInterface $bus,
private readonly DumpIdGeneratorInterface $dumpId,
InvokerInterface $invoker,
) {
parent::__construct($invoker);
}
private CommandBusInterface $commandBus,
private DumpIdGeneratorInterface $dumpId,
) {}

public function invoke(mixed $payload): void
public function handle(Request $request): ResponseInterface
{
$this->fireEvent(
(new MessageParser())->parse($payload),
);
}
if ($request->event === TcpEvent::Connected) {
return new ContinueRead();
}

$messages = \array_filter(\explode("\n", $request->body));

foreach ($messages as $message) {
$payload = (new MessageParser())->parse($message);

$this->fireEvent($payload);
}

return new ContinueRead();
}

private function fireEvent(ParsedPayload $payload): void
{
$this->bus->dispatch(
$this->commandBus->dispatch(
new HandleReceivedEvent(
type: 'var-dump',
payload: [
Expand Down Expand Up @@ -87,5 +96,4 @@ private function prepareContent(ParsedPayload $payload): array

return $payloadContent;
}

}
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ services:
args:
GH_TOKEN: "${GH_TOKEN}"
environment:
RR_LOG_LEVEL: debug
# RR_LOG_LEVEL: debug
# RR_LOG_TCP_LEVEL: debug
# RR_LOG_JOBS_LEVEL: debug
# RR_LOG_SERVER_LEVEL: debug
Expand Down
35 changes: 35 additions & 0 deletions tests/Feature/Interfaces/TCP/TCPTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
namespace Tests\Feature\Interfaces\TCP;

use Modules\Monolog\Interfaces\TCP\Service as MonologService;
use Modules\VarDumper\Interfaces\TCP\Service as VarDumperService;
use Modules\Smtp\Interfaces\TCP\Service as SmtpService;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Spiral\RoadRunner\Tcp\Request;
use Spiral\RoadRunner\Tcp\TcpEvent;
use Spiral\RoadRunnerBridge\Tcp\Response\ResponseInterface;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Tests\App\Smtp\FakeStream;
use Tests\DatabaseTestCase;

abstract class TCPTestCase extends DatabaseTestCase
Expand All @@ -19,6 +25,20 @@ public function handleMonologRequest(string $message): ResponseInterface
->handle($this->buildRequest(message: $message));
}

public function handleVarDumperRequest(string $message): ResponseInterface
{
return $this
->get(VarDumperService::class)
->handle($this->buildRequest(message: $message));
}

public function handleSmtpRequest(string $message, TcpEvent $event = TcpEvent::Data): ResponseInterface
{
return $this
->get(SmtpService::class)
->handle($this->buildRequest(message: $message, event: $event));
}

private function buildRequest(string $message, TcpEvent $event = TcpEvent::Data): Request
{
return new Request(
Expand All @@ -29,4 +49,19 @@ private function buildRequest(string $message, TcpEvent $event = TcpEvent::Data)
server: 'localhost',
);
}

protected function buildSmtpClient(string $username = 'homestead', ?UuidInterface $uuid = null): EsmtpTransport
{
$client = new EsmtpTransport(
stream: new FakeStream(
service: $this->get(SmtpService::class),
uuid: (string) $uuid ?? Uuid::uuid7(),
),
);

$client->setUsername($username);
$client->setPassword('password');

return $client;
}
}
35 changes: 35 additions & 0 deletions tests/Feature/Interfaces/TCP/VarDumper/SymfonyV6Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Tests\Feature\Interfaces\TCP\VarDumper;

use App\Application\Broadcasting\Channel\EventsChannel;
use Tests\Feature\Interfaces\TCP\TCPTestCase;

final class SymfonyV6Test extends TCPTestCase
{
public function testSendDump(): void
{
$payload = 'YToyOntpOjA7TzozOToiU3ltZm9ueVxDb21wb25lbnRcVmFyRHVtcGVyXENsb25lclxEYXRhIjo3OntzOjQ1OiIAU3ltZm9ueVxDb21wb25lbnRcVmFyRHVtcGVyXENsb25lclxEYXRhAGRhdGEiO2E6MTp7aTowO2E6MTp7aTowO3M6MzoiZm9vIjt9fXM6NDk6IgBTeW1mb255XENvbXBvbmVudFxWYXJEdW1wZXJcQ2xvbmVyXERhdGEAcG9zaXRpb24iO2k6MDtzOjQ0OiIAU3ltZm9ueVxDb21wb25lbnRcVmFyRHVtcGVyXENsb25lclxEYXRhAGtleSI7aTowO3M6NDk6IgBTeW1mb255XENvbXBvbmVudFxWYXJEdW1wZXJcQ2xvbmVyXERhdGEAbWF4RGVwdGgiO2k6MjA7czo1NzoiAFN5bWZvbnlcQ29tcG9uZW50XFZhckR1bXBlclxDbG9uZXJcRGF0YQBtYXhJdGVtc1BlckRlcHRoIjtpOi0xO3M6NTQ6IgBTeW1mb255XENvbXBvbmVudFxWYXJEdW1wZXJcQ2xvbmVyXERhdGEAdXNlUmVmSGFuZGxlcyI7aTotMTtzOjQ4OiIAU3ltZm9ueVxDb21wb25lbnRcVmFyRHVtcGVyXENsb25lclxEYXRhAGNvbnRleHQiO2E6MDp7fX1pOjE7YTozOntzOjk6InRpbWVzdGFtcCI7ZDoxNzAxNDk5NDM3LjUzODQ0NztzOjM6ImNsaSI7YToyOntzOjEyOiJjb21tYW5kX2xpbmUiO3M6MzIxOiIvcm9vdC9yZXBvcy9idWdncmVhZ3Rvci9zcGlyYWwtYXBwL3ZlbmRvci9waHB1bml0L3BocHVuaXQvcGhwdW5pdCAtLWNvbmZpZ3VyYXRpb24gL3Jvb3QvcmVwb3MvYnVnZ3JlYWd0b3Ivc3BpcmFsLWFwcC9waHB1bml0LnhtbCAtLWZpbHRlciAvKEludGVyZmFjZXNcXFRDUFxcVmFyRHVtcGVyXFxTeW1mb255VjZUZXN0Ojp0ZXN0U2VuZER1bXApKCAuKik/JC8gLS10ZXN0LXN1ZmZpeCBTeW1mb255VjZUZXN0LnBocCAvcm9vdC9yZXBvcy9idWdncmVhZ3Rvci9zcGlyYWwtYXBwL3Rlc3RzL0ZlYXR1cmUvSW50ZXJmYWNlcy9UQ1AvVmFyRHVtcGVyIC0tdGVhbWNpdHkiO3M6MTA6ImlkZW50aWZpZXIiO3M6ODoiZGVlMTBhZWUiO31zOjY6InNvdXJjZSI7YTo0OntzOjQ6Im5hbWUiO3M6MTc6IlN5bWZvbnlWNlRlc3QucGhwIjtzOjQ6ImZpbGUiO3M6OTE6Ii9yb290L3JlcG9zL2J1Z2dyZWFndG9yL3NwaXJhbC1hcHAvdGVzdHMvRmVhdHVyZS9JbnRlcmZhY2VzL1RDUC9WYXJEdW1wZXIvU3ltZm9ueVY2VGVzdC5waHAiO3M6NDoibGluZSI7aToxMztzOjEyOiJmaWxlX2V4Y2VycHQiO2I6MDt9fX0=';

$this->handleVarDumperRequest($payload);

$this->broadcastig->assertPushed(new EventsChannel('default'), function (array $data) {
$this->assertSame('event.received', $data['event']);
$this->assertSame('var-dump', $data['data']['type']);

$this->assertSame([
'type' => 'string',
'value' => 'foo',
'label' => null,
], $data['data']['payload']['payload']);

$this->assertNotEmpty($data['data']['uuid']);
$this->assertNotEmpty($data['data']['timestamp']);


return true;
});
}
}
Loading
Loading