Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add Flow\Driver\RevoltDriver #43

Merged
merged 1 commit into from
Sep 6, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## v1.1.x

- Add Flow\Driver\RevoltDriver
- Add more quality tools from https://github.com/IngeniozIT/php-skeleton

## v1.1.3
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
"react/async": "^4.1",
"symfony/doctrine-messenger": "^6.3",
"symfony/messenger": "^6.3",
"symfony/orm-pack": "^2.4"
"symfony/orm-pack": "^2.4",
"revolt/event-loop": "^1.0"
},
"suggest": {
"amphp/amp": "Provide asynchronous with AMP",
"ext-openswoole": "Provide asynchronous with OpenSwoole",
"react/async": "Provide asynchronous with ReactPHP",
"symfony/messenger": "Provide symfony messenger support"
"symfony/messenger": "Provide symfony messenger support",
"revolt/event-loop": "Provide asynchronous with Revolt"
},
"autoload": {
"psr-4": {
Expand Down
6 changes: 4 additions & 2 deletions examples/flow.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@
use Flow\Driver\AmpDriver;
use Flow\Driver\FiberDriver;
use Flow\Driver\ReactDriver;
use Flow\Driver\RevoltDriver;
use Flow\Driver\SwooleDriver;
use Flow\Flow\Flow;
use Flow\Ip;
use Flow\IpStrategy\MaxIpStrategy;

$driver = match (random_int(1, 4)) {
$driver = match (random_int(1, 5)) {
1 => new AmpDriver(),
2 => new ReactDriver(),
3 => new FiberDriver(),
4 => new SwooleDriver(),
4 => new RevoltDriver(),
5 => new SwooleDriver(),
};
printf("Use %s\n", $driver::class);

Expand Down
6 changes: 4 additions & 2 deletions examples/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@
use Flow\Driver\AmpDriver;
use Flow\Driver\FiberDriver;
use Flow\Driver\ReactDriver;
use Flow\Driver\RevoltDriver;
use Flow\Driver\SwooleDriver;
use Flow\Examples\Transport\DoctrineIpTransport;
use Flow\Flow\Flow;
use Flow\Flow\TransportFlow;
use Flow\IpStrategy\MaxIpStrategy;

$driver = match (random_int(1, 4)) {
$driver = match (random_int(1, 5)) {
1 => new AmpDriver(),
2 => new ReactDriver(),
3 => new FiberDriver(),
4 => new SwooleDriver(),
4 => new RevoltDriver(),
5 => new SwooleDriver(),
};
printf("Use %s\n", $driver::class);

Expand Down
32 changes: 5 additions & 27 deletions src/Driver/AmpDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@
use RuntimeException;
use Throwable;

use function Amp\async;
use function Amp\delay;
use function function_exists;

class AmpDriver implements DriverInterface
{
private int $counter = 0;

public function __construct()
{
if (!function_exists('Amp\\async')) {
Expand All @@ -27,8 +26,8 @@ public function __construct()

public function async(Closure $callback, Closure $onResolve = null): Closure
{
return function (...$args) use ($callback, $onResolve): void {
EventLoop::queue(function (Closure $callback, array $args, Closure $onResolve = null) {
return static function (...$args) use ($callback, $onResolve): void {
async(static function (Closure $callback, array $args, Closure $onResolve = null) {
try {
$return = $callback(...$args, ...($args = []));
if ($onResolve) {
Expand All @@ -38,11 +37,8 @@ public function async(Closure $callback, Closure $onResolve = null): Closure
if ($onResolve) {
$onResolve(new Exception($exception->getMessage(), $exception->getCode(), $exception));
}
} finally {
$this->pop();
}
}, $callback, $args, $onResolve);
$this->push();
}, $callback, $args, $onResolve)->await();
};
}

Expand All @@ -54,27 +50,9 @@ public function delay(float $seconds): void
public function tick(int $interval, Closure $callback): Closure
{
$tickId = EventLoop::repeat($interval / 1000, $callback);
$this->push();

return function () use ($tickId) {
return static function () use ($tickId) {
EventLoop::cancel($tickId);
$this->pop();
};
}

private function push(): void
{
if (/* $this->counter === 0 || */ !EventLoop::getDriver()->isRunning()) {
EventLoop::run();
}
$this->counter++;
}

private function pop(): void
{
$this->counter--;
if ($this->counter === 0) {
EventLoop::getDriver()->stop();
}
}
}
89 changes: 89 additions & 0 deletions src/Driver/RevoltDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

namespace Flow\Driver;

use Closure;
use Flow\DriverInterface;
use Flow\Exception;
use Revolt\EventLoop;
use Revolt\EventLoop\Driver;
use RuntimeException;
use Throwable;

class RevoltDriver implements DriverInterface
{
private int $counter = 0;

public function __construct(Driver $driver = null)
{
if (!class_exists('Revolt\\EventLoop')) {
throw new RuntimeException('Revolt is not loaded. Suggest install it with composer require revolt/event-loop');
}

if ($driver !== null) {
EventLoop::setDriver($driver);
}
}

public function async(Closure $callback, Closure $onResolve = null): Closure
{
return function (...$args) use ($callback, $onResolve): void {
EventLoop::queue(function (Closure $callback, array $args, Closure $onResolve = null) {
try {
$return = $callback(...$args, ...($args = []));
if ($onResolve) {
$onResolve($return);
}
} catch (Throwable $exception) {
if ($onResolve) {
$onResolve(new Exception($exception->getMessage(), $exception->getCode(), $exception));
}
} finally {
$this->pop();
}
}, $callback, $args, $onResolve);
$this->push();
};
}

public function delay(float $seconds): void
{
$suspension = EventLoop::getSuspension();
$callbackId = EventLoop::delay($seconds, static fn () => $suspension->resume());

try {
$suspension->suspend();
} finally {
EventLoop::cancel($callbackId);
}
}

public function tick(int $interval, Closure $callback): Closure
{
$tickId = EventLoop::repeat($interval / 1000, $callback);
$this->push();

return function () use ($tickId) {
EventLoop::cancel($tickId);
$this->pop();
};
}

private function push(): void
{
if (/* $this->counter === 0 || */ !EventLoop::getDriver()->isRunning()) {
EventLoop::run();
}
$this->counter++;
}

private function pop(): void
{
$this->counter--;
if ($this->counter === 0) {
EventLoop::getDriver()->stop();
}
}
}
11 changes: 11 additions & 0 deletions tests/Driver/AmpDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,20 @@

use Flow\Driver\AmpDriver;
use Flow\DriverInterface;
use Revolt\EventLoop;

class AmpDriverTest extends DriverTestCase
{
protected function setUp(): void
{
EventLoop::getDriver()->run();
}

protected function tearDown(): void
{
EventLoop::getDriver()->stop();
}

protected function createDriver(): DriverInterface
{
return new AmpDriver();
Expand Down
16 changes: 16 additions & 0 deletions tests/Driver/RevoltDriverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Flow\Test\Driver;

use Flow\Driver\RevoltDriver;
use Flow\DriverInterface;

class RevoltDriverTest extends DriverTestCase
{
protected function createDriver(): DriverInterface
{
return new RevoltDriver();
}
}
2 changes: 2 additions & 0 deletions tests/Flow/FlowTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Flow\Driver\AmpDriver;
use Flow\Driver\FiberDriver;
use Flow\Driver\ReactDriver;
use Flow\Driver\RevoltDriver;
use Flow\Driver\SwooleDriver;
use Flow\IpStrategy\LinearIpStrategy;
use Flow\IpStrategy\MaxIpStrategy;
Expand All @@ -24,6 +25,7 @@ protected static function matrix(Closure $datas): array
// 'amp' => fn (): AmpDriver => new AmpDriver(),
// 'fiber' => fn (): FiberDriver => new FiberDriver(),
'react' => static fn (): ReactDriver => new ReactDriver(),
// 'revolt' => static fn (): RevoltDriver => new RevoltDriver(),
// 'swoole' => fn (): SwooleDriver => new SwooleDriver(),
];

Expand Down