Merge pull request #963 from acelaya-forks/feature/mezzio-swoole-3

Feature/mezzio swoole 3
This commit is contained in:
Alejandro Celaya 2021-01-17 13:31:04 +01:00 committed by GitHub
commit 1309290a2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 111 additions and 55 deletions

View file

@ -21,3 +21,4 @@ infection*
**/test* **/test*
build* build*
**/.* **/.*
bin/helper

View file

@ -24,6 +24,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
### Changed ### Changed
* [#912](https://github.com/shlinkio/shlink/issues/912) Changed error templates to be plain html files, removing the dependency on `league/plates` package. * [#912](https://github.com/shlinkio/shlink/issues/912) Changed error templates to be plain html files, removing the dependency on `league/plates` package.
* [#875](https://github.com/shlinkio/shlink/issues/875) Updated to `mezzio/mezzio-swoole` v3.1.
### Deprecated ### Deprecated
* [#917](https://github.com/shlinkio/shlink/issues/917) Deprecated `/{shortCode}/qr-code/{size}` URL, in favor of providing the size in the query instead, `/{shortCode}/qr-code?size={size}`. * [#917](https://github.com/shlinkio/shlink/issues/917) Deprecated `/{shortCode}/qr-code/{size}` URL, in favor of providing the size in the query instead, `/{shortCode}/qr-code?size={size}`.

View file

@ -130,7 +130,7 @@ Once Shlink is configured, you need to expose it to the web, either by using a t
First you need to install the swoole PHP extension with [pecl](https://pecl.php.net/package/swoole), `pecl install swoole`. First you need to install the swoole PHP extension with [pecl](https://pecl.php.net/package/swoole), `pecl install swoole`.
Once installed, it's actually pretty easy to get shlink up and running with swoole. Run `./vendor/bin/mezzio-swoole start -d` and you will get shlink running on port 8080. Once installed, it's actually pretty easy to get shlink up and running with swoole. Run `./vendor/bin/laminas mezzio:swoole:start -d` and you will get shlink running on port 8080.
However, by doing it this way, you are loosing all the access logs, and the service won't be automatically run if the server has to be restarted. However, by doing it this way, you are loosing all the access logs, and the service won't be automatically run if the server has to be restarted.
@ -147,7 +147,7 @@ Once Shlink is configured, you need to expose it to the web, either by using a t
# Description: Shlink non-blocking server with swoole # Description: Shlink non-blocking server with swoole
### END INIT INFO ### END INIT INFO
SCRIPT=/path/to/shlink/vendor/bin/mezzio-swoole\ start SCRIPT=/path/to/shlink/vendor/bin/laminas\ mezzio:swoole:start
RUNAS=root RUNAS=root
PIDFILE=/var/run/shlink_swoole.pid PIDFILE=/var/run/shlink_swoole.pid

51
bin/helper/mezzio-swoole Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env php
<?php
/**
* @deprecated To be removed with Shlink 3.0.0
* This script is provided to keep backwards compatibility on how to run shlink with swoole while being still able to
* update to mezzio/mezzio-swoole 3.x
*/
declare(strict_types=1);
namespace Mezzio\Swoole\Command;
use Laminas\ServiceManager\ServiceManager;
use PackageVersions\Versions;
use Symfony\Component\Console\Application as CommandLine;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use function explode;
use function Functional\filter;
use function str_starts_with;
use function strstr;
/** @var ServiceManager $container */
$container = require __DIR__ . '/../../config/container.php';
$version = strstr(Versions::getVersion('mezzio/mezzio-swoole'), '@', true);
$commandsPrefix = 'mezzio:swoole:';
$commands = filter(
$container->get('config')['laminas-cli']['commands'] ?? [],
fn ($c, string $command) => str_starts_with($command, $commandsPrefix),
);
$registeredCommands = [];
foreach ($commands as $newName => $commandServiceName) {
[, $oldName] = explode($commandsPrefix, $newName);
$registeredCommands[$oldName] = $commandServiceName;
$container->addDelegator($commandServiceName, static function ($c, $n, callable $factory) use ($oldName) {
/** @var Command $command */
$command = $factory();
$command->setAliases([$oldName]);
return $command;
});
}
$commandLine = new CommandLine('Mezzio web server', $version);
$commandLine->setAutoExit(true);
$commandLine->setCommandLoader(new ContainerCommandLoader($container, $registeredCommands));
$commandLine->run();

View file

@ -4,16 +4,16 @@ export DB_DRIVER=mysql
export TEST_ENV=api export TEST_ENV=api
# Try to stop server just in case it hanged in last execution # Try to stop server just in case it hanged in last execution
vendor/bin/mezzio-swoole stop vendor/bin/laminas mezzio:swoole:stop
echo 'Starting server...' echo 'Starting server...'
vendor/bin/mezzio-swoole start -d vendor/bin/laminas mezzio:swoole:start -d
sleep 2 sleep 2
vendor/bin/phpunit --order-by=random -c phpunit-api.xml --testdox --colors=always --log-junit=build/coverage-api/junit.xml $* vendor/bin/phpunit --order-by=random -c phpunit-api.xml --testdox --colors=always --log-junit=build/coverage-api/junit.xml $*
testsExitCode=$? testsExitCode=$?
vendor/bin/mezzio-swoole stop vendor/bin/laminas mezzio:swoole:stop
# Exit this script with the same code as the tests. If tests failed, this script has to fail # Exit this script with the same code as the tests. If tests failed, this script has to fail
exit $testsExitCode exit $testsExitCode

View file

@ -28,6 +28,9 @@ echo "Installing dependencies with $composerBin..."
${composerBin} self-update ${composerBin} self-update
${composerBin} install --no-dev --optimize-autoloader --prefer-dist --no-progress --no-interaction ${composerBin} install --no-dev --optimize-autoloader --prefer-dist --no-progress --no-interaction
# Copy mezzio helper script to vendor (deprecated - Remove with Shlink 3.0.0)
cp "${projectdir}/bin/helper/mezzio-swoole" "./vendor/bin"
# Delete development files # Delete development files
echo 'Deleting dev files...' echo 'Deleting dev files...'
rm composer.* rm composer.*

View file

@ -39,7 +39,7 @@
"mezzio/mezzio-fastroute": "^3.1", "mezzio/mezzio-fastroute": "^3.1",
"mezzio/mezzio-helpers": "^5.3", "mezzio/mezzio-helpers": "^5.3",
"mezzio/mezzio-problem-details": "^1.1", "mezzio/mezzio-problem-details": "^1.1",
"mezzio/mezzio-swoole": "^2.6.4", "mezzio/mezzio-swoole": "^3.1",
"monolog/monolog": "^2.0", "monolog/monolog": "^2.0",
"nikolaposa/monolog-factory": "^3.1", "nikolaposa/monolog-factory": "^3.1",
"ocramius/proxy-manager": "^2.11", "ocramius/proxy-manager": "^2.11",
@ -49,7 +49,7 @@
"ramsey/uuid": "^3.9", "ramsey/uuid": "^3.9",
"shlinkio/shlink-common": "dev-main#1311861 as 3.4", "shlinkio/shlink-common": "dev-main#1311861 as 3.4",
"shlinkio/shlink-config": "^1.0", "shlinkio/shlink-config": "^1.0",
"shlinkio/shlink-event-dispatcher": "^1.6", "shlinkio/shlink-event-dispatcher": "^2.0",
"shlinkio/shlink-importer": "^2.1", "shlinkio/shlink-importer": "^2.1",
"shlinkio/shlink-installer": "^5.3", "shlinkio/shlink-installer": "^5.3",
"shlinkio/shlink-ip-geolocation": "^1.5", "shlinkio/shlink-ip-geolocation": "^1.5",

View file

@ -8,7 +8,7 @@
# Description: Shlink non-blocking server with swoole # Description: Shlink non-blocking server with swoole
### END INIT INFO ### END INIT INFO
SCRIPT=/path/to/shlink/vendor/bin/mezzio-swoole\ start SCRIPT=/path/to/shlink/vendor/bin/laminas\ mezzio:swoole:start
RUNAS=root RUNAS=root
PIDFILE=/var/run/shlink_swoole.pid PIDFILE=/var/run/shlink_swoole.pid

View file

@ -95,4 +95,4 @@ CMD \
if [[ ! -d "./vendor" ]]; then /usr/local/bin/composer install ; fi && \ if [[ ! -d "./vendor" ]]; then /usr/local/bin/composer install ; fi && \
# When restarting the container, swoole might think it is already in execution # When restarting the container, swoole might think it is already in execution
# This forces the app to be started every second until the exit code is 0 # This forces the app to be started every second until the exit code is 0
until php ./vendor/bin/mezzio-swoole start; do sleep 1 ; done until php ./vendor/bin/laminas mezzio:swoole:start; do sleep 1 ; done

View file

@ -17,4 +17,4 @@ php vendor/doctrine/orm/bin/doctrine.php orm:clear-cache:metadata -n -q
# When restarting the container, swoole might think it is already in execution # When restarting the container, swoole might think it is already in execution
# This forces the app to be started every second until the exit code is 0 # This forces the app to be started every second until the exit code is 0
until php vendor/mezzio/mezzio-swoole/bin/mezzio-swoole start; do sleep 1 ; done until php vendor/bin/laminas mezzio:swoole:start; do sleep 1 ; done

View file

@ -14,13 +14,13 @@ return [
'events' => [ 'events' => [
'regular' => [ 'regular' => [
EventDispatcher\VisitLocated::class => [ EventDispatcher\Event\VisitLocated::class => [
EventDispatcher\NotifyVisitToMercure::class, EventDispatcher\NotifyVisitToMercure::class,
EventDispatcher\NotifyVisitToWebHooks::class, EventDispatcher\NotifyVisitToWebHooks::class,
], ],
], ],
'async' => [ 'async' => [
EventDispatcher\ShortUrlVisited::class => [ EventDispatcher\Event\ShortUrlVisited::class => [
EventDispatcher\LocateShortUrlVisit::class, EventDispatcher\LocateShortUrlVisit::class,
], ],
], ],

View file

@ -2,13 +2,13 @@
declare(strict_types=1); declare(strict_types=1);
namespace Shlinkio\Shlink\Core\EventDispatcher; namespace Shlinkio\Shlink\Core\EventDispatcher\Event;
use JsonSerializable; use JsonSerializable;
final class VisitLocated implements JsonSerializable abstract class AbstractVisitEvent implements JsonSerializable
{ {
private string $visitId; protected string $visitId;
public function __construct(string $visitId) public function __construct(string $visitId)
{ {

View file

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\EventDispatcher\Event;
final class ShortUrlVisited extends AbstractVisitEvent
{
private ?string $originalIpAddress;
public function __construct(string $visitId, ?string $originalIpAddress = null)
{
parent::__construct($visitId);
$this->originalIpAddress = $originalIpAddress;
}
public function originalIpAddress(): ?string
{
return $this->originalIpAddress;
}
}

View file

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\EventDispatcher\Event;
final class VisitLocated extends AbstractVisitEvent
{
}

View file

@ -11,6 +11,8 @@ use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdaterInterface; use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdaterInterface;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\Entity\VisitLocation; use Shlinkio\Shlink\Core\Entity\VisitLocation;
use Shlinkio\Shlink\Core\EventDispatcher\Event\ShortUrlVisited;
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
use Shlinkio\Shlink\IpGeolocation\Exception\WrongIpException; use Shlinkio\Shlink\IpGeolocation\Exception\WrongIpException;
use Shlinkio\Shlink\IpGeolocation\Model\Location; use Shlinkio\Shlink\IpGeolocation\Model\Location;
use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface; use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface;

View file

@ -7,6 +7,7 @@ namespace Shlinkio\Shlink\Core\EventDispatcher;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
use Shlinkio\Shlink\Core\Mercure\MercureUpdatesGeneratorInterface; use Shlinkio\Shlink\Core\Mercure\MercureUpdatesGeneratorInterface;
use Symfony\Component\Mercure\PublisherInterface; use Symfony\Component\Mercure\PublisherInterface;
use Throwable; use Throwable;

View file

@ -13,6 +13,7 @@ use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\RequestOptions; use GuzzleHttp\RequestOptions;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Core\Options\AppOptions;
use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer; use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer;
use Throwable; use Throwable;

View file

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\EventDispatcher;
use JsonSerializable;
final class ShortUrlVisited implements JsonSerializable
{
private string $visitId;
private ?string $originalIpAddress;
public function __construct(string $visitId, ?string $originalIpAddress = null)
{
$this->visitId = $visitId;
$this->originalIpAddress = $originalIpAddress;
}
public function visitId(): string
{
return $this->visitId;
}
public function originalIpAddress(): ?string
{
return $this->originalIpAddress;
}
public function jsonSerialize(): array
{
return ['visitId' => $this->visitId, 'originalIpAddress' => $this->originalIpAddress];
}
}

View file

@ -10,7 +10,7 @@ use Psr\EventDispatcher\EventDispatcherInterface;
use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Entity\Tag; use Shlinkio\Shlink\Core\Entity\Tag;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\EventDispatcher\ShortUrlVisited; use Shlinkio\Shlink\Core\EventDispatcher\Event\ShortUrlVisited;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException; use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\Exception\TagNotFoundException; use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier; use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;

View file

@ -17,9 +17,9 @@ use Shlinkio\Shlink\Common\Util\IpAddress;
use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\Entity\VisitLocation; use Shlinkio\Shlink\Core\Entity\VisitLocation;
use Shlinkio\Shlink\Core\EventDispatcher\Event\ShortUrlVisited;
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
use Shlinkio\Shlink\Core\EventDispatcher\LocateShortUrlVisit; use Shlinkio\Shlink\Core\EventDispatcher\LocateShortUrlVisit;
use Shlinkio\Shlink\Core\EventDispatcher\ShortUrlVisited;
use Shlinkio\Shlink\Core\EventDispatcher\VisitLocated;
use Shlinkio\Shlink\Core\Model\Visitor; use Shlinkio\Shlink\Core\Model\Visitor;
use Shlinkio\Shlink\IpGeolocation\Exception\WrongIpException; use Shlinkio\Shlink\IpGeolocation\Exception\WrongIpException;
use Shlinkio\Shlink\IpGeolocation\Model\Location; use Shlinkio\Shlink\IpGeolocation\Model\Location;

View file

@ -13,8 +13,8 @@ use Psr\Log\LoggerInterface;
use RuntimeException; use RuntimeException;
use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
use Shlinkio\Shlink\Core\EventDispatcher\NotifyVisitToMercure; use Shlinkio\Shlink\Core\EventDispatcher\NotifyVisitToMercure;
use Shlinkio\Shlink\Core\EventDispatcher\VisitLocated;
use Shlinkio\Shlink\Core\Mercure\MercureUpdatesGeneratorInterface; use Shlinkio\Shlink\Core\Mercure\MercureUpdatesGeneratorInterface;
use Shlinkio\Shlink\Core\Model\Visitor; use Shlinkio\Shlink\Core\Model\Visitor;
use Symfony\Component\Mercure\PublisherInterface; use Symfony\Component\Mercure\PublisherInterface;

View file

@ -19,8 +19,8 @@ use Prophecy\Prophecy\ObjectProphecy;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
use Shlinkio\Shlink\Core\EventDispatcher\NotifyVisitToWebHooks; use Shlinkio\Shlink\Core\EventDispatcher\NotifyVisitToWebHooks;
use Shlinkio\Shlink\Core\EventDispatcher\VisitLocated;
use Shlinkio\Shlink\Core\Model\Visitor; use Shlinkio\Shlink\Core\Model\Visitor;
use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Core\Options\AppOptions;

View file

@ -15,7 +15,7 @@ use Shlinkio\Shlink\Common\Util\DateRange;
use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Entity\Tag; use Shlinkio\Shlink\Core\Entity\Tag;
use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\EventDispatcher\ShortUrlVisited; use Shlinkio\Shlink\Core\EventDispatcher\Event\ShortUrlVisited;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException; use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\Exception\TagNotFoundException; use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier; use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;