Skip to content

Commit

Permalink
Upgrade to Centrifugo v4 (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
fre5h authored Nov 14, 2023
1 parent cee50eb commit 14ab877
Show file tree
Hide file tree
Showing 117 changed files with 5,167 additions and 577 deletions.
12 changes: 9 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: 'Setup PHP'
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 8.2
ini-values: memory_limit=-1
coverage: none
tools: composer:v2
Expand All @@ -66,7 +66,7 @@ jobs:
- name: 'Setup PHP'
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 8.2
ini-values: memory_limit=-1
coverage: none
tools: composer:v2
Expand All @@ -87,8 +87,14 @@ jobs:
matrix:
php-version:
- '8.1'
- '8.2'
symfony-version:
- '5.4'
- '6.0'
- '6.1'
- '6.2'
- '6.3'
- '6.4'
steps:
- name: 'Checkout Code'
uses: actions/checkout@v2
Expand Down Expand Up @@ -123,7 +129,7 @@ jobs:
- name: 'Setup PHP'
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 8.2
ini-values: memory_limit=-1
coverage: pcov
tools: composer:v2
Expand Down
16 changes: 11 additions & 5 deletions Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,21 @@
*/
abstract class AbstractCommand extends Command
{
protected CentrifugoInterface $centrifugo;

/**
* @param CentrifugoInterface $centrifugo
*/
public function __construct(CentrifugoInterface $centrifugo)
public function __construct(protected readonly CentrifugoInterface $centrifugo)
{
$this->centrifugo = $centrifugo;

parent::__construct();
}

/**
* @return \Closure
*/
public function getChannelsForAutocompletion(): \Closure
{
return function () {
return \array_keys($this->centrifugo->channels()['channels']);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

declare(strict_types=1);

namespace Fresh\CentrifugoBundle\Command;
namespace Fresh\CentrifugoBundle\Command\Argument;

use Fresh\CentrifugoBundle\Service\CentrifugoChecker;
use Symfony\Component\Console\Exception\InvalidArgumentException;
Expand All @@ -24,7 +24,7 @@
trait ArgumentChannelTrait
{
protected string $channel;
protected CentrifugoChecker $centrifugoChecker;
protected readonly CentrifugoChecker $centrifugoChecker;

/**
* @param InputInterface $input
Expand All @@ -35,6 +35,10 @@ protected function initializeChannelArgument(InputInterface $input): void
{
$channel = $input->getArgument('channel');

if (null === $channel) {
throw new InvalidArgumentException('Argument "channel" is required.');
}

if (!\is_string($channel)) {
throw new InvalidArgumentException('Argument "channel" is not a string.');
}
Expand Down
49 changes: 49 additions & 0 deletions Command/Argument/ArgumentChannelsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/*
* This file is part of the FreshCentrifugoBundle.
*
* (c) Artem Henvald <genvaldartem@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Fresh\CentrifugoBundle\Command\Argument;

use Fresh\CentrifugoBundle\Service\CentrifugoChecker;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;

/**
* ArgumentChannelsTrait.
*
* @author Artem Henvald <genvaldartem@gmail.com>
*/
trait ArgumentChannelsTrait
{
protected readonly CentrifugoChecker $centrifugoChecker;

/** @var string[] */
private array $channels;

/**
* @param InputInterface $input
*
* @throws InvalidArgumentException
*/
protected function initializeChannelsArgument(InputInterface $input): void
{
try {
/** @var string[] $channels */
$channels = (array) $input->getArgument('channels');
foreach ($channels as $channel) {
$this->centrifugoChecker->assertValidChannelName($channel);
}
$this->channels = $channels;
} catch (\Throwable $e) {
throw new InvalidArgumentException($e->getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

declare(strict_types=1);

namespace Fresh\CentrifugoBundle\Command;
namespace Fresh\CentrifugoBundle\Command\Argument;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -22,7 +22,7 @@
*/
trait ArgumentDataTrait
{
/** @var array */
/** @var array<string, mixed> */
protected array $data = [];

/**
Expand Down
37 changes: 37 additions & 0 deletions Command/Argument/ArgumentPatternTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the FreshCentrifugoBundle.
*
* (c) Artem Henvald <genvaldartem@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Fresh\CentrifugoBundle\Command\Argument;

use Symfony\Component\Console\Input\InputInterface;

/**
* ArgumentPatternTrait.
*
* @author Artem Henvald <genvaldartem@gmail.com>
*/
trait ArgumentPatternTrait
{
protected ?string $pattern = null;

/**
* @param InputInterface $input
*/
protected function initializePatternArgument(InputInterface $input): void
{
$pattern = $input->getArgument('pattern');

if (\is_string($pattern) && !empty($pattern)) {
$this->pattern = $pattern;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

declare(strict_types=1);

namespace Fresh\CentrifugoBundle\Command;
namespace Fresh\CentrifugoBundle\Command\Argument;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
Expand Down
74 changes: 50 additions & 24 deletions Command/BroadcastCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@

namespace Fresh\CentrifugoBundle\Command;

use Fresh\CentrifugoBundle\Command\Argument\ArgumentChannelsTrait;
use Fresh\CentrifugoBundle\Command\Argument\ArgumentDataTrait;
use Fresh\CentrifugoBundle\Command\Option\OptionBase64DataTrait;
use Fresh\CentrifugoBundle\Command\Option\OptionSkipHistoryTrait;
use Fresh\CentrifugoBundle\Command\Option\OptionTagsTrait;
use Fresh\CentrifugoBundle\Service\CentrifugoChecker;
use Fresh\CentrifugoBundle\Service\CentrifugoInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpKernel\Kernel;

/**
* BroadcastCommand.
Expand All @@ -30,21 +36,18 @@
#[AsCommand(name: 'centrifugo:broadcast', description: 'Publish same data into many channels')]
final class BroadcastCommand extends AbstractCommand
{
use ArgumentChannelsTrait;
use ArgumentDataTrait;

private CentrifugoChecker $centrifugoChecker;

/** @var string[] */
private array $channels;
use OptionBase64DataTrait;
use OptionSkipHistoryTrait;
use OptionTagsTrait;

/**
* @param CentrifugoInterface $centrifugo
* @param CentrifugoChecker $centrifugoChecker
*/
public function __construct(CentrifugoInterface $centrifugo, CentrifugoChecker $centrifugoChecker)
public function __construct(CentrifugoInterface $centrifugo, protected readonly CentrifugoChecker $centrifugoChecker)
{
$this->centrifugoChecker = $centrifugoChecker;

parent::__construct($centrifugo);
}

Expand All @@ -53,20 +56,44 @@ public function __construct(CentrifugoInterface $centrifugo, CentrifugoChecker $
*/
protected function configure(): void
{
if (Kernel::MAJOR_VERSION >= 6) { // @phpstan-ignore-line
$channelsArgument = new InputArgument('channels', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'List of channels to publish data to', null, $this->getChannelsForAutocompletion());
} else { // @phpstan-ignore-line
$channelsArgument = new InputArgument('channels', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'List of channels to publish data to');
}

$this
->setDefinition(
new InputDefinition([
new InputArgument('data', InputArgument::REQUIRED, 'Data in JSON format'),
new InputArgument('channels', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'Channel names'),
$channelsArgument,
new InputOption('tags', null, InputOption::VALUE_OPTIONAL, 'Publication tags - map with arbitrary string keys and values which is attached to publication and will be delivered to clients'),
new InputOption('skipHistory', null, InputOption::VALUE_NONE, 'Skip adding publication to history for this request'),
new InputOption('base64data', null, InputOption::VALUE_OPTIONAL, 'Custom binary data to publish into a channel encoded to base64 so it\'s possible to use HTTP API to send binary to clients. Centrifugo will decode it from base64 before publishing.'),
])
)
->setHelp(
<<<'HELP'
The <info>%command.name%</info> command allows to publish same data into many channels:
<info>%command.full_name%</info> <comment>'{"foo":"bar"}'</comment> </comment>channelAbc</comment> </comment>channelDef</comment>
<info>%command.full_name%</info> <comment>'{"foo":"bar"}'</comment> </comment>channelName1</comment> </comment>channelName2</comment>
You can skip adding publication to history for this request:
<info>%command.full_name%</info> <comment>'{"foo":"bar"}'</comment> </comment>channelName1</comment> </comment>channelName2</comment> <comment>--skipHistory</comment>
You can add tags which are attached to publication and will be delivered to clients:
Read more at https://centrifugal.github.io/centrifugo/server/http_api/#broadcast
<info>%command.full_name%</info> <comment>'{"foo":"bar"}'</comment> </comment>channelName1</comment> </comment>channelName2</comment> <comment>--tags='{"tag1":"value1","tag2":"value2"}'</comment>
You can add custom binary data to publish into a channel encoded to base64, so it's possible to use
HTTP API to send binary to clients. Centrifugo will decode it from base64 before publishing:
<info>%command.full_name%</info> <comment>'{"foo":"bar"}'</comment> </comment>channelName1</comment> </comment>channelName2</comment> <comment>--base64data=SGVsbG8gd29ybGQ=</comment>
Where <comment>SGVsbG8gd29ybGQ=</comment> is base64 encoded version of <comment>Hello world</comment>
Read more at https://centrifugal.dev/docs/server/server_api#broadcast
HELP
)
;
Expand All @@ -79,18 +106,11 @@ protected function initialize(InputInterface $input, OutputInterface $output): v
{
parent::initialize($input, $output);

$this->initializeChannelsArgument($input);
$this->initializeDataArgument($input);

try {
/** @var string[] $channels */
$channels = (array) $input->getArgument('channels');
foreach ($channels as $channel) {
$this->centrifugoChecker->assertValidChannelName($channel);
}
$this->channels = $channels;
} catch (\Throwable $e) {
throw new InvalidArgumentException($e->getMessage());
}
$this->initializeTagsOption($input);
$this->initializeSkipHistoryOption($input);
$this->initializeB64DataOption($input);
}

/**
Expand All @@ -101,7 +121,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$io = new SymfonyStyle($input, $output);

try {
$this->centrifugo->broadcast($this->data, $this->channels);
$this->centrifugo->broadcast(
data: $this->data,
channels: $this->channels,
skipHistory: $this->skipHistory,
tags: $this->tags,
base64data: $this->base64data,
);
$io->success('DONE');
} catch (\Throwable $e) {
$io->error($e->getMessage());
Expand Down
Loading

0 comments on commit 14ab877

Please sign in to comment.