spiral / roadrunner-bridge

🌉 RoadRunner bridge to Spiral Framework
https://spiral.dev/docs/packages-roadrunner-bridge
MIT License
12 stars 6 forks source link

Enhancements to Centrifugo Handler Class Generator #95

Closed butschster closed 8 months ago

butschster commented 8 months ago

This pull request introduces significant improvements to the class generator for Centrifugo handlers. The refactor enhances the functionality of the generator, enabling it to create diverse handler types catering to various aspects of Centrifugo server interaction.

Changes

  1. Expanded Handler Types: The generator now supports multiple handler types: connect, subscribe, rpc, refresh, and publish. Each type corresponds to different interactions with the Centrifugo server, providing tailored functionality for specific use cases.

  2. Default Handler Type: The default command (php app.php create:centrifugo-handler Simple) now generates a connect type handler, aligning with the most common use case.

  3. Enhanced Code Templates: Each handler type comes with its specific code template, ensuring that generated classes are immediately relevant and useful. This update enhances developer experience and reduces the need for manual modifications post-generation.

Before

<?php

declare(strict_types=1);

namespace Spiral\Testing\Endpoint\Centrifugo\Handler;

use RoadRunner\Centrifugo\CentrifugoApiInterface;

/**
 * Sample Handler
 */
final class SampleHandler
{
    public function __construct(
        private readonly CentrifugoApiInterface $api,
    ) {
    }

    public function handle(): void
    {
         // ...
    }
}

Here are example of handlers:

Connect

Command:

php app.php create:centrifugo-handler Connect

Result:

<?php

declare(strict_types=1);

namespace Spiral\Testing\Endpoint\Centrifugo\Handler;

use RoadRunner\Centrifugo\Payload\ConnectResponse;
use RoadRunner\Centrifugo\Request\Connect;
use RoadRunner\Centrifugo\Request\RequestInterface;
use Spiral\RoadRunnerBridge\Centrifugo\ServiceInterface;

final class ConnectHandler implements ServiceInterface
{
    /**
     * @param Connect $request
     */
    public function handle(RequestInterface $request): void
    {
        try {
            $request->respond(
                new ConnectResponse(
                    user: '', // User ID
                    channels: [
                        // List of channels to subscribe to on connect to Centrifugo
                        // 'public',
                    ],
                )
            );
        } catch (\Throwable $e) {
            $request->error($e->getCode(), $e->getMessage());
        }
    }
}

Subscribe

Command:

php app.php create:centrifugo-handler Subscribe -t=subscribe

Result:

<?php

declare(strict_types=1);

namespace Spiral\Testing\Endpoint\Centrifugo\Handler;

use RoadRunner\Centrifugo\Payload\SubscribeResponse;
use RoadRunner\Centrifugo\Request\RequestInterface;
use RoadRunner\Centrifugo\Request\Subscribe;
use Spiral\RoadRunnerBridge\Centrifugo\ServiceInterface;

final class SubscribeHandler implements ServiceInterface
{
    /**
     * @param Subscribe $request
     */
    public function handle(RequestInterface $request): void
    {
        try {
            // Here you can check if user is allowed to subscribe to requested channel
            if ($request->channel !== 'public') {
                $request->disconnect('403', 'Channel is not allowed.');
                return;
            }

            $request->respond(
                new SubscribeResponse()
            );
        } catch (\Throwable $e) {
            $request->error($e->getCode(), $e->getMessage());
        }
    }
}

RPC

Command:

php app.php create:centrifugo-handler Rpc -t=rpc

Result:

<?php

declare(strict_types=1);

namespace Spiral\Testing\Endpoint\Centrifugo\Handler;

use RoadRunner\Centrifugo\Payload\RPCResponse;
use RoadRunner\Centrifugo\Request\RPC;
use RoadRunner\Centrifugo\Request\RequestInterface;
use Spiral\RoadRunnerBridge\Centrifugo\ServiceInterface;

final class RpcHandler implements ServiceInterface
{
    /**
     * @param RPC $request
     */
    public function handle(RequestInterface $request): void
    {
        $result = match ($request->method) {
            'ping' => ['pong' => 'pong', 'code' => 200],
            default => ['error' => 'Not found', 'code' => 404]
        };

        try {
            $request->respond(
                new RPCResponse(
                    data: $result
                )
            );
        } catch (\Throwable $e) {
            $request->error($e->getCode(), $e->getMessage());
        }
    }
}

Refresh

Command:

php app.php create:centrifugo-handler Refresh -t=refresh

Result:

<?php

declare(strict_types=1);

namespace Spiral\Testing\Endpoint\Centrifugo\Handler;

use RoadRunner\Centrifugo\Payload\RefreshResponse;
use RoadRunner\Centrifugo\Request\Refresh;
use RoadRunner\Centrifugo\Request\RequestInterface;
use Spiral\RoadRunnerBridge\Centrifugo\ServiceInterface;

final class RefreshHandler implements ServiceInterface
{
    /**
     * @param Refresh $request
     */
    public function handle(RequestInterface $request): void
    {
        try {
            $request->respond(
                new RefreshResponse(...)
            );
        } catch (\Throwable $e) {
            $request->error($e->getCode(), $e->getMessage());
        }
    }
}

Publish

Command:

php app.php create:centrifugo-handler Publish -t=publish

Result:

<?php

declare(strict_types=1);

namespace Spiral\Testing\Endpoint\Centrifugo\Handler;

use RoadRunner\Centrifugo\Payload\PublishResponse;
use RoadRunner\Centrifugo\Request\Publish;
use RoadRunner\Centrifugo\Request\RequestInterface;
use Spiral\RoadRunnerBridge\Centrifugo\ServiceInterface;

final class PublishHandler implements ServiceInterface
{
    /**
     * @param Publish $request
     */
    public function handle(RequestInterface $request): void
    {
        try {
            $request->respond(
                new PublishResponse(...)
            );
        } catch (\Throwable $e) {
            $request->error($e->getCode(), $e->getMessage());
        }
    }
}
  1. Improved Command Output: The output of the generator command has been enriched with additional information. It now not only confirms the successful creation of the handler but also provides next steps and references to relevant documentation, improving guidance for further development.

Before

Declaration of 'SampleHandler' has been successfully written into 'app/src/Endpoint/Centrifugo/Handler/SampleHandler.php

After

Declaration of 'SampleHandler' has been successfully written into 'app/src/Endpoint/Centrifugo/Handler/SampleHandler.php'.

Next steps:
1. Register your handler in `app/config/centrifugo.php` file. Read more in the documentation: https://spiral.dev/docs/websockets-services#service-registration
2. Read more about Centrifugo handlers: https://spiral.dev/docs/websockets-services

This enhancement fosters a more efficient and streamlined workflow for developers working with Centrifugo in our PHP environment. It not only saves time but also ensures consistency and adherence to best practices across different types of handlers.

codecov[bot] commented 8 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Comparison is base (9206d2a) 93.11% compared to head (adbadd0) 93.46%.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## 3.x #95 +/- ## ============================================ + Coverage 93.11% 93.46% +0.34% - Complexity 351 356 +5 ============================================ Files 64 64 Lines 1177 1240 +63 ============================================ + Hits 1096 1159 +63 Misses 81 81 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.