From 955c9fb090ab79a47dbdd2466409914762a92587 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Tue, 3 Sep 2024 02:04:55 +0200 Subject: [PATCH 01/14] :sparkles: Add count event --- CHANGELOG.md | 5 +++ examples/flow.php | 2 +- src/AsyncHandler/AsyncHandler.php | 25 +++++++++++- src/AsyncHandler/BatchAsyncHandler.php | 18 +++++--- src/AsyncHandler/DeferAsyncHandler.php | 23 ++++++++++- src/AsyncHandlerInterface.php | 6 +++ src/Driver/AmpDriver.php | 6 +-- src/Driver/DriverTrait.php | 27 ++++++++++++ src/Driver/FiberDriver.php | 9 ++-- src/Driver/ReactDriver.php | 6 +-- src/Driver/SpatieDriver.php | 8 ++-- src/Driver/SwooleDriver.php | 8 ++-- src/DriverInterface.php | 2 +- src/Event.php | 9 ++++ src/Event/PoolEvent.php | 43 ++++++++++++++++++++ src/Flow/Flow.php | 2 - src/IpPool.php | 40 ++++++++++++++++++ src/IpStrategy/LinearIpStrategy.php | 7 ++++ src/IpStrategy/MaxIpStrategy.php | 10 ++++- src/IpStrategy/StackIpStrategy.php | 7 ++++ src/IpStrategyInterface.php | 9 +++- tests/AsyncHandler/AsyncHandlerTest.php | 4 +- tests/AsyncHandler/BatchAsyncHandlerTest.php | 8 ++-- 23 files changed, 245 insertions(+), 39 deletions(-) create mode 100644 src/Driver/DriverTrait.php create mode 100644 src/Event/PoolEvent.php create mode 100644 src/IpPool.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b17280b..285224ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v1.2.x + +- Add event Event::POOL occurs when Flow needs to count IPs to process. +- Add `Flow\IpPool` for managing pools of Ips. + ## v1.2.2 - Flow can now use `Flow\JobInterface` as job input diff --git a/examples/flow.php b/examples/flow.php index 3a4ec3cf..63fb476e 100644 --- a/examples/flow.php +++ b/examples/flow.php @@ -35,7 +35,7 @@ $job1 = static function (DataA $dataA) use ($driver): DataB { printf("*. #%d - Job 1 Calculating %d + %d\n", $dataA->id, $dataA->a, $dataA->b); - // simulating calculating some "light" operation from 0.1 to 1 seconds + // simulating calculating some "light" operation from 1 to 3 seconds $delay = random_int(1, 3); $driver->delay($delay); $d = $dataA->a + $dataA->b; diff --git a/src/AsyncHandler/AsyncHandler.php b/src/AsyncHandler/AsyncHandler.php index c81c5cc7..941258d7 100644 --- a/src/AsyncHandler/AsyncHandler.php +++ b/src/AsyncHandler/AsyncHandler.php @@ -7,6 +7,8 @@ use Flow\AsyncHandlerInterface; use Flow\Event; use Flow\Event\AsyncEvent; +use Flow\Event\PoolEvent; +use Flow\IpPool; /** * @template T @@ -15,10 +17,21 @@ */ final class AsyncHandler implements AsyncHandlerInterface { + /** + * @var IpPool + */ + private IpPool $ipPool; + + public function __construct() + { + $this->ipPool = new IpPool(); + } + public static function getSubscribedEvents() { return [ Event::ASYNC => 'async', + Event::POOL => 'pool', ]; } @@ -27,7 +40,17 @@ public function async(AsyncEvent $event): void $ip = $event->getIp(); $async = $event->getAsync(); $asyncJob = $async($event->getJob()); + + $popIp = $this->ipPool->addIp($ip); $next = $asyncJob($ip->data); - $next($event->getCallback()); + $next(static function ($data) use ($event, $popIp) { + $event->getCallback()($data); + $popIp(); + }); + } + + public function pool(PoolEvent $event): void + { + $event->addIps($this->ipPool->getIps()); } } diff --git a/src/AsyncHandler/BatchAsyncHandler.php b/src/AsyncHandler/BatchAsyncHandler.php index 54625085..9f674677 100644 --- a/src/AsyncHandler/BatchAsyncHandler.php +++ b/src/AsyncHandler/BatchAsyncHandler.php @@ -7,28 +7,28 @@ use Flow\AsyncHandlerInterface; use Flow\Event; use Flow\Event\AsyncEvent; +use Flow\Event\PoolEvent; use Symfony\Component\Messenger\Handler\Acknowledger; use Symfony\Component\Messenger\Handler\BatchHandlerInterface; use Symfony\Component\Messenger\Handler\BatchHandlerTrait; use Throwable; /** - * @template T1 - * @template T2 + * @template T * - * @implements AsyncHandlerInterface + * @implements AsyncHandlerInterface */ final class BatchAsyncHandler implements BatchHandlerInterface, AsyncHandlerInterface { use BatchHandlerTrait; /** - * @var AsyncHandlerInterface + * @var AsyncHandlerInterface */ private AsyncHandlerInterface $asyncHandler; /** - * @param null|AsyncHandlerInterface $asyncHandler + * @param null|AsyncHandlerInterface $asyncHandler */ public function __construct( private int $batchSize = 10, @@ -41,6 +41,7 @@ public static function getSubscribedEvents() { return [ Event::ASYNC => 'async', + Event::POOL => 'pool', ]; } @@ -53,12 +54,17 @@ public function async(AsyncEvent $event): void $this->handle($event, $ack); } + public function pool(PoolEvent $event): void + { + $this->asyncHandler->pool($event); + } + /** * PHPStan should normaly pass for method.unused * https://github.com/phpstan/phpstan/issues/6039 * https://phpstan.org/r/8f7de023-9888-4dcb-b12c-e2fcf9547b6c. * - * @param array{0: AsyncEvent, 1: Acknowledger}[] $jobs + * @param array{0: AsyncEvent, 1: Acknowledger}[] $jobs * * @phpstan-ignore method.unused */ diff --git a/src/AsyncHandler/DeferAsyncHandler.php b/src/AsyncHandler/DeferAsyncHandler.php index b36727a9..3c0f1d9e 100644 --- a/src/AsyncHandler/DeferAsyncHandler.php +++ b/src/AsyncHandler/DeferAsyncHandler.php @@ -7,6 +7,8 @@ use Flow\AsyncHandlerInterface; use Flow\Event; use Flow\Event\AsyncEvent; +use Flow\Event\PoolEvent; +use Flow\IpPool; /** * @template T @@ -15,10 +17,21 @@ */ final class DeferAsyncHandler implements AsyncHandlerInterface { + /** + * @var IpPool + */ + private IpPool $ipPool; + + public function __construct() + { + $this->ipPool = new IpPool(); + } + public static function getSubscribedEvents() { return [ Event::ASYNC => 'async', + Event::POOL => 'pool', ]; } @@ -26,11 +39,19 @@ public function async(AsyncEvent $event): void { $ip = $event->getIp(); $job = $event->getJob(); + + $popIp = $this->ipPool->addIp($ip); $next = $job([$ip->data, $event->getDefer()]); - $next(static function ($result) use ($event) { + $next(static function ($result) use ($event, $popIp) { [$data] = $result; $callback = $event->getCallback(); $callback($data); + $popIp(); }); } + + public function pool(PoolEvent $event): void + { + $event->addIps($this->ipPool->getIps()); + } } diff --git a/src/AsyncHandlerInterface.php b/src/AsyncHandlerInterface.php index c66ce8df..01a6a1fa 100644 --- a/src/AsyncHandlerInterface.php +++ b/src/AsyncHandlerInterface.php @@ -5,6 +5,7 @@ namespace Flow; use Flow\Event\AsyncEvent; +use Flow\Event\PoolEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -16,4 +17,9 @@ interface AsyncHandlerInterface extends EventSubscriberInterface * @param AsyncEvent $event */ public function async(AsyncEvent $event): void; + + /** + * @param PoolEvent $event + */ + public function pool(PoolEvent $event): void; } diff --git a/src/Driver/AmpDriver.php b/src/Driver/AmpDriver.php index c4b95b45..89d732bd 100644 --- a/src/Driver/AmpDriver.php +++ b/src/Driver/AmpDriver.php @@ -34,6 +34,8 @@ */ class AmpDriver implements DriverInterface { + use DriverTrait; + private int $ticks = 0; public function __construct(?Driver $driver = null) @@ -121,18 +123,16 @@ public function await(array &$stream): void $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); - $stream['ips']++; $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); } $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - $stream['ips']--; }), Event::ASYNC); } } } while ($nextIp !== null); - if ($stream['ips'] > 0 or $this->ticks > 0) { + if ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0) { EventLoop::defer($loop); } else { EventLoop::getDriver()->stop(); diff --git a/src/Driver/DriverTrait.php b/src/Driver/DriverTrait.php new file mode 100644 index 00000000..ee4c2233 --- /dev/null +++ b/src/Driver/DriverTrait.php @@ -0,0 +1,27 @@ + $dispatchers + */ + public function countIps(array $dispatchers): int + { + $count = 0; + foreach ($dispatchers as $dispatcher) { + $count += count($dispatcher->dispatch(new PoolEvent(), Event::POOL)->getIps()); + } + + return $count; + } +} diff --git a/src/Driver/FiberDriver.php b/src/Driver/FiberDriver.php index 451297fe..1706ba09 100644 --- a/src/Driver/FiberDriver.php +++ b/src/Driver/FiberDriver.php @@ -30,6 +30,8 @@ */ class FiberDriver implements DriverInterface { + use DriverTrait; + /** * @var array */ @@ -121,7 +123,7 @@ public function await(array &$stream): void $tick = 0; $fiberDatas = []; - while ($stream['ips'] > 0 or count($this->ticks) > 0) { + do { foreach ($this->ticks as [ 'interval' => $interval, 'callback' => $callback, @@ -136,6 +138,7 @@ public function await(array &$stream): void do { foreach ($stream['dispatchers'] as $index => $dispatcher) { $nextIp = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIp(); + if ($nextIp !== null) { $stream['dispatchers'][$index]->dispatch(new AsyncEvent(static function (Closure|JobInterface $job) use ($async) { return $async(false)($job); @@ -146,12 +149,10 @@ public function await(array &$stream): void $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); - $stream['ips']++; $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); } $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - $stream['ips']--; }), Event::ASYNC); } } @@ -168,7 +169,7 @@ public function await(array &$stream): void } $tick++; - } + } while ($this->countIps($stream['dispatchers']) > 0 or count($this->ticks) > 0); } public function delay(float $seconds): void diff --git a/src/Driver/ReactDriver.php b/src/Driver/ReactDriver.php index 0d016563..2225079e 100644 --- a/src/Driver/ReactDriver.php +++ b/src/Driver/ReactDriver.php @@ -34,6 +34,8 @@ */ class ReactDriver implements DriverInterface { + use DriverTrait; + private int $ticks = 0; private LoopInterface $eventLoop; @@ -114,18 +116,16 @@ public function await(array &$stream): void $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); - $stream['ips']++; $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); } $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - $stream['ips']--; }), Event::ASYNC); } } } while ($nextIp !== null); - if ($stream['ips'] > 0 or $this->ticks > 0) { + if ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0) { $this->eventLoop->futureTick($loop); } else { $this->eventLoop->stop(); diff --git a/src/Driver/SpatieDriver.php b/src/Driver/SpatieDriver.php index b008e5d2..80a4503c 100644 --- a/src/Driver/SpatieDriver.php +++ b/src/Driver/SpatieDriver.php @@ -30,6 +30,8 @@ */ class SpatieDriver implements DriverInterface { + use DriverTrait; + private int $ticks = 0; private Pool $pool; @@ -89,7 +91,7 @@ public function await(array &$stream): void }; $nextIp = null; - while ($stream['ips'] > 0 or $this->ticks > 0) { + do { do { foreach ($stream['dispatchers'] as $index => $dispatcher) { $nextIp = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIp(); @@ -99,17 +101,15 @@ public function await(array &$stream): void $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); - $stream['ips']++; $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); } $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - $stream['ips']--; }), Event::ASYNC); } } } while ($nextIp !== null); - } + } while ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0); } public function delay(float $seconds): void diff --git a/src/Driver/SwooleDriver.php b/src/Driver/SwooleDriver.php index 413c99dd..2c6e9e97 100644 --- a/src/Driver/SwooleDriver.php +++ b/src/Driver/SwooleDriver.php @@ -30,6 +30,8 @@ */ class SwooleDriver implements DriverInterface { + use DriverTrait; + private int $ticks = 0; public function __construct() @@ -85,7 +87,7 @@ public function await(array &$stream): void }; co::run(function () use (&$stream, $async, $defer) { - while ($stream['ips'] > 0 or $this->ticks > 0) { + do { $nextIp = null; do { foreach ($stream['dispatchers'] as $index => $dispatcher) { @@ -96,18 +98,16 @@ public function await(array &$stream): void $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); - $stream['ips']++; $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); } $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - $stream['ips']--; }), Event::ASYNC); } } co::sleep(1); } while ($nextIp !== null); - } + } while ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0); }); } diff --git a/src/DriverInterface.php b/src/DriverInterface.php index 69a588b7..c33d16ad 100644 --- a/src/DriverInterface.php +++ b/src/DriverInterface.php @@ -30,7 +30,7 @@ public function async(Closure|JobInterface $callback): Closure; public function defer(Closure $callback): mixed; /** - * @param array{'ips': int, 'fnFlows': array, 'dispatchers': array} $stream + * @param array{'fnFlows': array, 'dispatchers': array} $stream */ public function await(array &$stream): void; diff --git a/src/Event.php b/src/Event.php index c8a8a02b..fa1515f7 100644 --- a/src/Event.php +++ b/src/Event.php @@ -41,4 +41,13 @@ final class Event * @Event("Flow\Event\PopEvent") */ public const POP = 'pop'; + + /** + * The POOL event occurs when Flow need to get the pool IPs to process. + * + * This event allows you to get the pool IPs to process. + * + * @Event("Flow\Event\PoolEvent") + */ + public const POOL = 'pool'; } diff --git a/src/Event/PoolEvent.php b/src/Event/PoolEvent.php new file mode 100644 index 00000000..bedf7860 --- /dev/null +++ b/src/Event/PoolEvent.php @@ -0,0 +1,43 @@ + + */ + private IpPool $ipPool; + + public function __construct() + { + $this->ipPool = new IpPool(); + } + + /** + * @param array> $ips + */ + public function addIps(array $ips): void + { + foreach ($ips as $ip) { + $this->ipPool->addIp($ip); + } + } + + /** + * @return array> + */ + public function getIps(): array + { + return $this->ipPool->getIps(); + } +} diff --git a/src/Flow/Flow.php b/src/Flow/Flow.php index 511bd24a..a5f588fc 100644 --- a/src/Flow/Flow.php +++ b/src/Flow/Flow.php @@ -37,7 +37,6 @@ class Flow implements FlowInterface * @var array */ private array $stream = [ - 'ips' => 0, 'fnFlows' => [], 'dispatchers' => [], ]; @@ -89,7 +88,6 @@ public function __construct( public function __invoke(Ip $ip): void { - $this->stream['ips']++; $this->stream['dispatchers'][0]->dispatch(new PushEvent($ip), Event::PUSH); } diff --git a/src/IpPool.php b/src/IpPool.php new file mode 100644 index 00000000..db052a04 --- /dev/null +++ b/src/IpPool.php @@ -0,0 +1,40 @@ +> + */ + private array $ips = []; + + /** + * @param Ip $ip + * + * @return callable A function that removes the added IP from the pool when called + */ + public function addIp(Ip $ip): callable + { + $this->ips[] = $ip; + + return function () use ($ip) { + $this->ips = array_filter($this->ips, static function ($iteratorIp) use ($ip) { + return $iteratorIp !== $ip; + }); + }; + } + + /** + * @return array> + */ + public function getIps(): array + { + return $this->ips; + } +} diff --git a/src/IpStrategy/LinearIpStrategy.php b/src/IpStrategy/LinearIpStrategy.php index 775df2b1..f965e5ab 100644 --- a/src/IpStrategy/LinearIpStrategy.php +++ b/src/IpStrategy/LinearIpStrategy.php @@ -5,6 +5,7 @@ namespace Flow\IpStrategy; use Flow\Event; +use Flow\Event\PoolEvent; use Flow\Event\PullEvent; use Flow\Event\PushEvent; use Flow\Ip; @@ -27,6 +28,7 @@ public static function getSubscribedEvents(): array return [ Event::PUSH => 'push', Event::PULL => 'pull', + Event::POOL => 'pool', ]; } @@ -45,4 +47,9 @@ public function pull(PullEvent $event): void { $event->setIp(array_shift($this->ips)); } + + public function pool(PoolEvent $event): void + { + $event->addIps($this->ips); + } } diff --git a/src/IpStrategy/MaxIpStrategy.php b/src/IpStrategy/MaxIpStrategy.php index e3238399..1eb9a4a7 100644 --- a/src/IpStrategy/MaxIpStrategy.php +++ b/src/IpStrategy/MaxIpStrategy.php @@ -5,6 +5,7 @@ namespace Flow\IpStrategy; use Flow\Event; +use Flow\Event\PoolEvent; use Flow\Event\PopEvent; use Flow\Event\PullEvent; use Flow\Event\PushEvent; @@ -47,6 +48,7 @@ public static function getSubscribedEvents() Event::PUSH => 'push', Event::PULL => 'pull', Event::POP => 'pop', + Event::POOL => 'pool', ]; } @@ -67,9 +69,8 @@ public function pull(PullEvent $event): void $ip = $this->dispatcher->dispatch($event, Event::PULL)->getIp(); if ($ip) { $this->processing++; + $event->setIp($ip); } - - $event->setIp($ip); } } @@ -81,4 +82,9 @@ public function pop(PopEvent $event): void $this->dispatcher->dispatch($event, Event::POP); $this->processing--; } + + public function pool(PoolEvent $event): void + { + $event->addIps($this->dispatcher->dispatch($event, Event::POOL)->getIps()); + } } diff --git a/src/IpStrategy/StackIpStrategy.php b/src/IpStrategy/StackIpStrategy.php index af2c506d..09c23572 100644 --- a/src/IpStrategy/StackIpStrategy.php +++ b/src/IpStrategy/StackIpStrategy.php @@ -5,6 +5,7 @@ namespace Flow\IpStrategy; use Flow\Event; +use Flow\Event\PoolEvent; use Flow\Event\PullEvent; use Flow\Event\PushEvent; use Flow\Ip; @@ -27,6 +28,7 @@ public static function getSubscribedEvents() return [ Event::PUSH => 'push', Event::PULL => 'pull', + Event::POOL => 'pool', ]; } @@ -45,4 +47,9 @@ public function pull(PullEvent $event): void { $event->setIp(array_pop($this->ips)); } + + public function pool(PoolEvent $event): void + { + $event->addIps($this->ips); + } } diff --git a/src/IpStrategyInterface.php b/src/IpStrategyInterface.php index 1953c285..13e106fe 100644 --- a/src/IpStrategyInterface.php +++ b/src/IpStrategyInterface.php @@ -4,9 +4,16 @@ namespace Flow; +use Flow\Event\PoolEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * @template T */ -interface IpStrategyInterface extends EventSubscriberInterface {} +interface IpStrategyInterface extends EventSubscriberInterface +{ + /** + * @param PoolEvent $event + */ + public function pool(PoolEvent $event): void; +} diff --git a/tests/AsyncHandler/AsyncHandlerTest.php b/tests/AsyncHandler/AsyncHandlerTest.php index a1f6cf78..6bddb264 100644 --- a/tests/AsyncHandler/AsyncHandlerTest.php +++ b/tests/AsyncHandler/AsyncHandlerTest.php @@ -24,8 +24,8 @@ static function ($data) use (&$result) { [$n1, $n2] = $data; $result = $n1 + $n2; - return static function ($callback) { - $callback(); + return static function ($callback) use ($result) { + $callback($result); }; }, new Ip([2, 6]), diff --git a/tests/AsyncHandler/BatchAsyncHandlerTest.php b/tests/AsyncHandler/BatchAsyncHandlerTest.php index bc2bad52..5ec6d01f 100644 --- a/tests/AsyncHandler/BatchAsyncHandlerTest.php +++ b/tests/AsyncHandler/BatchAsyncHandlerTest.php @@ -24,8 +24,8 @@ static function ($data) use (&$result1) { [$n1, $n2] = $data; $result1 = $n1 + $n2; - return static function ($callback) { - $callback(); + return static function ($callback) use ($result1) { + $callback($result1); }; }, new Ip([2, 6]), @@ -41,8 +41,8 @@ static function ($data) use (&$result2) { [$n1, $n2] = $data; $result2 = $n1 + $n2; - return static function ($callback) { - $callback(); + return static function ($callback) use ($result2) { + $callback($result2); }; }, new Ip([6, 10]), From 12207c1da43e0172bdfd61932701ac3157690a65 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Wed, 4 Sep 2024 00:03:16 +0200 Subject: [PATCH 02/14] :recycle: Update LinearIpStrategy and StackIpStrategy --- src/IpPool.php | 16 ++++++++++++++++ src/IpStrategy/LinearIpStrategy.php | 17 +++++++++++------ src/IpStrategy/StackIpStrategy.php | 17 +++++++++++------ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/IpPool.php b/src/IpPool.php index db052a04..0ee63c5a 100644 --- a/src/IpPool.php +++ b/src/IpPool.php @@ -37,4 +37,20 @@ public function getIps(): array { return $this->ips; } + + /** + * @return null|Ip + */ + public function shiftIp(): ?Ip + { + return array_shift($this->ips); + } + + /** + * @return null|Ip + */ + public function popIp(): ?Ip + { + return array_pop($this->ips); + } } diff --git a/src/IpStrategy/LinearIpStrategy.php b/src/IpStrategy/LinearIpStrategy.php index f965e5ab..2bc8795b 100644 --- a/src/IpStrategy/LinearIpStrategy.php +++ b/src/IpStrategy/LinearIpStrategy.php @@ -8,7 +8,7 @@ use Flow\Event\PoolEvent; use Flow\Event\PullEvent; use Flow\Event\PushEvent; -use Flow\Ip; +use Flow\IpPool; use Flow\IpStrategyInterface; /** @@ -19,9 +19,14 @@ class LinearIpStrategy implements IpStrategyInterface { /** - * @var array> + * @var IpPool */ - private array $ips = []; + private IpPool $ipPool; + + public function __construct() + { + $this->ipPool = new IpPool(); + } public static function getSubscribedEvents(): array { @@ -37,7 +42,7 @@ public static function getSubscribedEvents(): array */ public function push(PushEvent $event): void { - $this->ips[] = $event->getIp(); + $this->ipPool->addIp($event->getIp()); } /** @@ -45,11 +50,11 @@ public function push(PushEvent $event): void */ public function pull(PullEvent $event): void { - $event->setIp(array_shift($this->ips)); + $event->setIp($this->ipPool->shiftIp()); } public function pool(PoolEvent $event): void { - $event->addIps($this->ips); + $event->addIps($this->ipPool->getIps()); } } diff --git a/src/IpStrategy/StackIpStrategy.php b/src/IpStrategy/StackIpStrategy.php index 09c23572..1f24618d 100644 --- a/src/IpStrategy/StackIpStrategy.php +++ b/src/IpStrategy/StackIpStrategy.php @@ -8,7 +8,7 @@ use Flow\Event\PoolEvent; use Flow\Event\PullEvent; use Flow\Event\PushEvent; -use Flow\Ip; +use Flow\IpPool; use Flow\IpStrategyInterface; /** @@ -19,9 +19,14 @@ class StackIpStrategy implements IpStrategyInterface { /** - * @var array> + * @var IpPool */ - private array $ips = []; + private IpPool $ipPool; + + public function __construct() + { + $this->ipPool = new IpPool(); + } public static function getSubscribedEvents() { @@ -37,7 +42,7 @@ public static function getSubscribedEvents() */ public function push(PushEvent $event): void { - $this->ips[] = $event->getIp(); + $this->ipPool->addIp($event->getIp()); } /** @@ -45,11 +50,11 @@ public function push(PushEvent $event): void */ public function pull(PullEvent $event): void { - $event->setIp(array_pop($this->ips)); + $event->setIp($this->ipPool->popIp()); } public function pool(PoolEvent $event): void { - $event->addIps($this->ips); + $event->addIps($this->ipPool->getIps()); } } From b0e61d557d5dfda01573eb79509e830c0edd68de Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Wed, 4 Sep 2024 01:26:42 +0200 Subject: [PATCH 03/14] :recycle: Update PullEvent --- CHANGELOG.md | 1 + src/Driver/AmpDriver.php | 35 +++++++++----------- src/Driver/FiberDriver.php | 40 ++++++++++------------- src/Driver/ReactDriver.php | 35 +++++++++----------- src/Driver/SpatieDriver.php | 31 ++++++++---------- src/Driver/SwooleDriver.php | 33 +++++++++---------- src/Event.php | 2 +- src/Event/PullEvent.php | 22 ++++++++----- src/IpStrategy/LinearIpStrategy.php | 5 ++- src/IpStrategy/MaxIpStrategy.php | 10 +++--- src/IpStrategy/StackIpStrategy.php | 5 ++- tests/IpStrategy/LinearIpStrategyTest.php | 10 +++--- tests/IpStrategy/MaxIpStrategyTest.php | 8 ++--- tests/IpStrategy/StackIpStrategyTest.php | 10 +++--- 14 files changed, 123 insertions(+), 124 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 285224ad..f2e8e89a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Add event Event::POOL occurs when Flow needs to count IPs to process. - Add `Flow\IpPool` for managing pools of Ips. +- Update `Flow\Event\PullEvent` to pull multiple Ips instead one. ## v1.2.2 diff --git a/src/Driver/AmpDriver.php b/src/Driver/AmpDriver.php index 89d732bd..14650814 100644 --- a/src/Driver/AmpDriver.php +++ b/src/Driver/AmpDriver.php @@ -111,26 +111,23 @@ public function await(array &$stream): void }; $loop = function () use (&$loop, &$stream, $async, $defer) { - $nextIp = null; - do { - foreach ($stream['dispatchers'] as $index => $dispatcher) { - $nextIp = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIp(); - if ($nextIp !== null) { - $job = $stream['fnFlows'][$index]['job']; - - $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $job, $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { - $stream['fnFlows'][$index]['errorJob']($data); - } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { - $ip = new Ip($data); - $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); - } - - $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - }), Event::ASYNC); - } + foreach ($stream['dispatchers'] as $index => $dispatcher) { + $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); + foreach ($nextIps as $nextIp) { + $job = $stream['fnFlows'][$index]['job']; + + $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $job, $nextIp, static function ($data) use (&$stream, $index, $nextIp) { + if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + $stream['fnFlows'][$index]['errorJob']($data); + } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { + $ip = new Ip($data); + $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); + } + + $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); + }), Event::ASYNC); } - } while ($nextIp !== null); + } if ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0) { EventLoop::defer($loop); diff --git a/src/Driver/FiberDriver.php b/src/Driver/FiberDriver.php index 1706ba09..2fdb3cef 100644 --- a/src/Driver/FiberDriver.php +++ b/src/Driver/FiberDriver.php @@ -134,29 +134,25 @@ public function await(array &$stream): void } } - $nextIp = null; - do { - foreach ($stream['dispatchers'] as $index => $dispatcher) { - $nextIp = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIp(); - - if ($nextIp !== null) { - $stream['dispatchers'][$index]->dispatch(new AsyncEvent(static function (Closure|JobInterface $job) use ($async) { - return $async(false)($job); - }, static function (Closure|JobInterface $job) use ($defer) { - return $defer(false)($job); - }, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) and $stream['fnFlows'][$index]['errorJob'] !== null) { - $stream['fnFlows'][$index]['errorJob']($data); - } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { - $ip = new Ip($data); - $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); - } - - $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - }), Event::ASYNC); - } + foreach ($stream['dispatchers'] as $index => $dispatcher) { + $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); + foreach ($nextIps as $nextIp) { + $stream['dispatchers'][$index]->dispatch(new AsyncEvent(static function (Closure|JobInterface $job) use ($async) { + return $async(false)($job); + }, static function (Closure|JobInterface $job) use ($defer) { + return $defer(false)($job); + }, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { + if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) and $stream['fnFlows'][$index]['errorJob'] !== null) { + $stream['fnFlows'][$index]['errorJob']($data); + } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { + $ip = new Ip($data); + $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); + } + + $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); + }), Event::ASYNC); } - } while ($nextIp !== null); + } foreach ($fiberDatas as $i => $fiberData) { // @phpstan-ignore-line see https://github.com/phpstan/phpstan/issues/11468 if (!$fiberData['fiber']->isTerminated() and $fiberData['fiber']->isSuspended()) { diff --git a/src/Driver/ReactDriver.php b/src/Driver/ReactDriver.php index 2225079e..96c21fb4 100644 --- a/src/Driver/ReactDriver.php +++ b/src/Driver/ReactDriver.php @@ -104,26 +104,23 @@ public function await(array &$stream): void }; $loop = function () use (&$loop, &$stream, $async, $defer) { - $nextIp = null; - do { - foreach ($stream['dispatchers'] as $index => $dispatcher) { - $nextIp = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIp(); - if ($nextIp !== null) { - $job = $stream['fnFlows'][$index]['job']; - - $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $job, $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { - $stream['fnFlows'][$index]['errorJob']($data); - } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { - $ip = new Ip($data); - $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); - } - - $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - }), Event::ASYNC); - } + foreach ($stream['dispatchers'] as $index => $dispatcher) { + $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); + foreach ($nextIps as $nextIp) { + $job = $stream['fnFlows'][$index]['job']; + + $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $job, $nextIp, static function ($data) use (&$stream, $index, $nextIp) { + if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + $stream['fnFlows'][$index]['errorJob']($data); + } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { + $ip = new Ip($data); + $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); + } + + $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); + }), Event::ASYNC); } - } while ($nextIp !== null); + } if ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0) { $this->eventLoop->futureTick($loop); diff --git a/src/Driver/SpatieDriver.php b/src/Driver/SpatieDriver.php index 80a4503c..75d3c097 100644 --- a/src/Driver/SpatieDriver.php +++ b/src/Driver/SpatieDriver.php @@ -90,25 +90,22 @@ public function await(array &$stream): void }; }; - $nextIp = null; do { - do { - foreach ($stream['dispatchers'] as $index => $dispatcher) { - $nextIp = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIp(); - if ($nextIp !== null) { - $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { - $stream['fnFlows'][$index]['errorJob']($data); - } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { - $ip = new Ip($data); - $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); - } - - $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - }), Event::ASYNC); - } + foreach ($stream['dispatchers'] as $index => $dispatcher) { + $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); + foreach ($nextIps as $nextIp) { + $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { + if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + $stream['fnFlows'][$index]['errorJob']($data); + } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { + $ip = new Ip($data); + $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); + } + + $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); + }), Event::ASYNC); } - } while ($nextIp !== null); + } } while ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0); } diff --git a/src/Driver/SwooleDriver.php b/src/Driver/SwooleDriver.php index 2c6e9e97..46340479 100644 --- a/src/Driver/SwooleDriver.php +++ b/src/Driver/SwooleDriver.php @@ -88,25 +88,22 @@ public function await(array &$stream): void co::run(function () use (&$stream, $async, $defer) { do { - $nextIp = null; - do { - foreach ($stream['dispatchers'] as $index => $dispatcher) { - $nextIp = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIp(); - if ($nextIp !== null) { - $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { - $stream['fnFlows'][$index]['errorJob']($data); - } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { - $ip = new Ip($data); - $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); - } - - $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); - }), Event::ASYNC); - } + foreach ($stream['dispatchers'] as $index => $dispatcher) { + $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); + foreach ($nextIps as $nextIp) { + $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { + if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + $stream['fnFlows'][$index]['errorJob']($data); + } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { + $ip = new Ip($data); + $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); + } + + $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); + }), Event::ASYNC); } - co::sleep(1); - } while ($nextIp !== null); + } + co::sleep(1); } while ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0); }); } diff --git a/src/Event.php b/src/Event.php index fa1515f7..560597e4 100644 --- a/src/Event.php +++ b/src/Event.php @@ -27,7 +27,7 @@ final class Event /** * The PULL event occurs when Flow need a next IP to async process. * - * This event allows you to choose what IP come next from your pushed IPs and will be used for async process execution. + * This event allows you to choose what IPs come next from your pushed IPs and will be used for async process execution. * * @Event("Flow\Event\PullEvent") */ diff --git a/src/Event/PullEvent.php b/src/Event/PullEvent.php index f9c429fa..e401542a 100644 --- a/src/Event/PullEvent.php +++ b/src/Event/PullEvent.php @@ -5,6 +5,7 @@ namespace Flow\Event; use Flow\Ip; +use Flow\IpPool; use Symfony\Contracts\EventDispatcher\Event; /** @@ -13,23 +14,28 @@ final class PullEvent extends Event { /** - * @var null|Ip + * @var IpPool */ - private ?Ip $ip = null; + private IpPool $ipPool; + + public function __construct() + { + $this->ipPool = new IpPool(); + } /** - * @return null|Ip + * @return Ip[] */ - public function getIp(): ?Ip + public function getIps(): array { - return $this->ip; + return $this->ipPool->getIps(); } /** - * @param null|Ip $ip + * @param Ip $ip */ - public function setIp(?Ip $ip): void + public function addIp(Ip $ip): void { - $this->ip = $ip; + $this->ipPool->addIp($ip); } } diff --git a/src/IpStrategy/LinearIpStrategy.php b/src/IpStrategy/LinearIpStrategy.php index 2bc8795b..133536d6 100644 --- a/src/IpStrategy/LinearIpStrategy.php +++ b/src/IpStrategy/LinearIpStrategy.php @@ -50,7 +50,10 @@ public function push(PushEvent $event): void */ public function pull(PullEvent $event): void { - $event->setIp($this->ipPool->shiftIp()); + $ip = $this->ipPool->shiftIp(); + if ($ip !== null) { + $event->addIp($ip); + } } public function pool(PoolEvent $event): void diff --git a/src/IpStrategy/MaxIpStrategy.php b/src/IpStrategy/MaxIpStrategy.php index 1eb9a4a7..f789a1af 100644 --- a/src/IpStrategy/MaxIpStrategy.php +++ b/src/IpStrategy/MaxIpStrategy.php @@ -65,11 +65,13 @@ public function push(PushEvent $event): void */ public function pull(PullEvent $event): void { - if ($this->processing < $this->max) { - $ip = $this->dispatcher->dispatch($event, Event::PULL)->getIp(); - if ($ip) { + $ips = $this->dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); + foreach ($ips as $ip) { + if ($this->processing < $this->max) { $this->processing++; - $event->setIp($ip); + $event->addIp($ip); + } else { + $this->dispatcher->dispatch(new PushEvent($ip), Event::PUSH); } } } diff --git a/src/IpStrategy/StackIpStrategy.php b/src/IpStrategy/StackIpStrategy.php index 1f24618d..132573fe 100644 --- a/src/IpStrategy/StackIpStrategy.php +++ b/src/IpStrategy/StackIpStrategy.php @@ -50,7 +50,10 @@ public function push(PushEvent $event): void */ public function pull(PullEvent $event): void { - $event->setIp($this->ipPool->popIp()); + $ip = $this->ipPool->popIp(); + if ($ip !== null) { + $event->addIp($ip); + } } public function pool(PoolEvent $event): void diff --git a/tests/IpStrategy/LinearIpStrategyTest.php b/tests/IpStrategy/LinearIpStrategyTest.php index 10e44a07..ea5d6b22 100644 --- a/tests/IpStrategy/LinearIpStrategyTest.php +++ b/tests/IpStrategy/LinearIpStrategyTest.php @@ -23,16 +23,16 @@ public function testStrategy(): void $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - self::assertNotNull($pullEvent->getIp()); - self::assertSame($ip1, $pullEvent->getIp()); + self::assertNotEmpty($pullEvent->getIps()); + self::assertSame($ip1, $pullEvent->getIps()[0]); $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - self::assertNotNull($pullEvent->getIp()); - self::assertSame($ip2, $pullEvent->getIp()); + self::assertNotEmpty($pullEvent->getIps()); + self::assertSame($ip2, $pullEvent->getIps()[0]); $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - self::assertNull($pullEvent->getIp()); + self::assertEmpty($pullEvent->getIps()); } } diff --git a/tests/IpStrategy/MaxIpStrategyTest.php b/tests/IpStrategy/MaxIpStrategyTest.php index 0ccb61c4..7363be3c 100644 --- a/tests/IpStrategy/MaxIpStrategyTest.php +++ b/tests/IpStrategy/MaxIpStrategyTest.php @@ -27,24 +27,24 @@ public function testStrategy(int $doneIndex): void $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - $ips[] = $pullEvent->getIp(); + $ips[] = $pullEvent->getIps()[0] ?? null; self::assertNotNull($ips[0]); $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - $ips[] = $pullEvent->getIp(); + $ips[] = $pullEvent->getIps()[0] ?? null; self::assertNotNull($ips[1]); $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - $ips[] = $pullEvent->getIp(); + $ips[] = $pullEvent->getIps()[0] ?? null; self::assertNull($ips[2]); $strategy->pop(new PopEvent($ips[$doneIndex])); $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - $ips[] = $pullEvent->getIp(); + $ips[] = $pullEvent->getIps()[0] ?? null; self::assertNotNull($ips[3]); } diff --git a/tests/IpStrategy/StackIpStrategyTest.php b/tests/IpStrategy/StackIpStrategyTest.php index e3b72a60..738e5cdc 100644 --- a/tests/IpStrategy/StackIpStrategyTest.php +++ b/tests/IpStrategy/StackIpStrategyTest.php @@ -23,16 +23,16 @@ public function testStrategy(): void $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - self::assertNotNull($pullEvent->getIp()); - self::assertSame($ip2, $pullEvent->getIp()); + self::assertNotEmpty($pullEvent->getIps()); + self::assertSame($ip2, $pullEvent->getIps()[0]); $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - self::assertNotNull($pullEvent->getIp()); - self::assertSame($ip1, $pullEvent->getIp()); + self::assertNotEmpty($pullEvent->getIps()); + self::assertSame($ip1, $pullEvent->getIps()[0]); $pullEvent = new PullEvent(); $strategy->pull($pullEvent); - self::assertNull($pullEvent->getIp()); + self::assertEmpty($pullEvent->getIps()); } } From c3d2860b85997df18ab9933b833d174a2d26a5c2 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Sat, 7 Sep 2024 17:25:51 +0200 Subject: [PATCH 04/14] :hammer: add fibonacci --- examples/yflow.php | 89 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 16 deletions(-) diff --git a/examples/yflow.php b/examples/yflow.php index 7d845d63..5a0a253e 100644 --- a/examples/yflow.php +++ b/examples/yflow.php @@ -75,18 +75,18 @@ function factorialYMemo(int $n): int } $factorialJob = static function (YFlowData $data): YFlowData { - printf("*... #%d - Job 1 : Calculating factorial(%d)\n", $data->id, $data->number); + printf("*.... #%d - Job 1 : Calculating factorial(%d)\n", $data->id, $data->number); // raw factorial calculation $result = factorial($data->number); - printf("*... #%d - Job 1 : Result for factorial(%d) = %d\n", $data->id, $data->number, $result); + printf("*.... #%d - Job 1 : Result for factorial(%d) = %d\n", $data->id, $data->number, $result); return new YFlowData($data->id, $data->number); }; $factorialYJobBefore = static function (YFlowData $data): YFlowData { - printf(".*.. #%d - Job 2 : Calculating factorialYJob(%d)\n", $data->id, $data->number); + printf(".*... #%d - Job 2 : Calculating factorialYJob(%d)\n", $data->id, $data->number); return new YFlowData($data->id, $data->number, $data->number); }; @@ -102,37 +102,44 @@ function factorialYMemo(int $n): int }; $factorialYJobAfter = static function (YFlowData $data): YFlowData { - printf(".*.. #%d - Job 2 : Result for factorialYJob(%d) = %d\n", $data->id, $data->number, $data->result); + printf(".*... #%d - Job 2 : Result for factorialYJob(%d) = %d\n", $data->id, $data->number, $data->result); return new YFlowData($data->id, $data->number); }; -$factorialYMemoJob = static function (YFlowData $data): YFlowData { - printf("..*. #%d - Job 3 : Calculating factorialYMemo(%d)\n", $data->id, $data->number); +$factorialYMemoJob = static function (YFlowData $data) use ($driver): YFlowData { + printf("..*.. #%d - Job 3 : Calculating factorialYMemo(%d)\n", $data->id, $data->number); + $driver->delay(3); $result = factorialYMemo($data->number); - printf("..*. #%d - Job 3 : Result for factorialYMemo(%d) = %d\n", $data->id, $data->number, $result); + printf("..*.. #%d - Job 3 : Result for factorialYMemo(%d) = %d\n", $data->id, $data->number, $result); return new YFlowData($data->id, $data->number); }; -$factorialYJobDeferBefore = static function (YFlowData $data) { - printf("...* #%d - Job 4 : Calculating factorialYJobDefer(%d)\n", $data->id, $data->number); +$factorialYJobDeferBefore = static function (YFlowData $data) use ($driver) { + printf("...*.. #%d - Job 4 : Calculating factorialYJobDefer(%d)\n", $data->id, $data->number); return new YFlowData($data->id, $data->number, $data->number); }; -$factorialYJobDefer = new YJob(static function ($factorial) { - return static function ($args) use ($factorial) { +$factorialYJobDefer = new YJob(static function ($factorial) use ($driver) { + return static function ($args) use ($factorial, $driver) { [$data, $defer] = $args; - return $defer(static function ($complete, $async) use ($data, $defer, $factorial) { + return $defer(static function ($complete, $async) use ($data, $defer, $factorial, $driver) { if ($data->result <= 1) { + $delay = random_int(1, 3); + printf("...*.. #%d - Job 4 : Step factorialYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); + $driver->delay($delay); $complete([new YFlowData($data->id, $data->number, 1), $defer]); } else { - $async($factorial([new YFlowData($data->id, $data->number, $data->result - 1), $defer]), static function ($result) use ($data, $complete) { + $async($factorial([new YFlowData($data->id, $data->number, $data->result - 1), $defer]), static function ($result) use ($data, $complete, $driver) { [$resultData, $defer] = $result; + $delay = random_int(1, 3); + printf("...*.. #%d - Job 4 : Step async factorialYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); + $driver->delay($delay); $complete([new YFlowData($data->id, $data->number, $data->result * $resultData->result), $defer]); }); } @@ -144,12 +151,56 @@ function factorialYMemo(int $n): int [$data, $defer] = $args; return $defer(static function ($complete) use ($data, $defer) { - printf("...* #%d - Job 4 : Result for factorialYJobDefer(%d) = %d\n", $data->id, $data->number, $data->result); + printf("...*.. #%d - Job 4 : Result for factorialYJobDefer(%d) = %d\n", $data->id, $data->number, $data->result); $complete([new YFlowData($data->id, $data->number), $defer]); }); }; +$fibonacciYJobDeferBefore = static function (YFlowData $data) use ($driver) { + printf("....* #%d - Job 5 : Calculating fibonacciYJobDefer(%d)\n", $data->id, $data->number); + + return new YFlowData($data->id, $data->number, $data->number); +}; + +$fibonacciYJobDefer = new YJob(static function ($fibonacci) use ($driver) { + return static function ($args) use ($fibonacci, $driver) { + [$data, $defer] = $args; + + return $defer(static function ($complete, $async) use ($data, $defer, $fibonacci, $driver) { + if ($data->result <= 1) { + $delay = random_int(1, 3); + printf("....* #%d - Job 5 : Step fibonacciYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); + $driver->delay($delay); + $complete([new YFlowData($data->id, $data->number, 1), $defer]); + } else { + $async($fibonacci([new YFlowData($data->id, $data->number, $data->result - 1), $defer]), function ($result1) use ($data, $complete, $driver, $async, $fibonacci, $defer) { + [$resultData1, $defer1] = $result1; + $async($fibonacci([new YFlowData($data->id, $data->number, $data->result - 2), $defer1]), function ($result2) use ($data, $complete, $driver, $resultData1) { + [$resultData2, $defer2] = $result2; + $delay = random_int(1, 3); + printf("....* #%d - Job 5 : Step async fibonacciYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); + $driver->delay($delay); + $fibResult = $resultData1->result + $resultData2->result; + $complete([new YFlowData($data->id, $data->number, $fibResult), $defer2]); + }); + }); + } + }); + }; +}); + +$fibonacciYJobDeferAfter = static function ($args) { + [$data, $defer] = $args; + + return $defer(static function ($complete) use ($data, $defer) { + printf("....* #%d - Job 5 : Result for fibonacciYJobDefer(%d) = %d\n", $data->id, $data->number, $data->result); + + $complete([new YFlowData($data->id, $data->number), $defer]); + }); +}; + + $flow = Flow::do(static function () use ( $factorialJob, $factorialYJobBefore, @@ -158,7 +209,10 @@ function factorialYMemo(int $n): int $factorialYMemoJob, $factorialYJobDeferBefore, $factorialYJobDefer, - $factorialYJobDeferAfter + $factorialYJobDeferAfter, + $fibonacciYJobDeferBefore, + $fibonacciYJobDefer, + $fibonacciYJobDeferAfter ) { yield [$factorialJob]; yield [$factorialYJobBefore]; @@ -168,9 +222,12 @@ function factorialYMemo(int $n): int yield [$factorialYJobDeferBefore]; yield [$factorialYJobDefer, null, null, null, new DeferAsyncHandler()]; yield [$factorialYJobDeferAfter, null, null, null, new DeferAsyncHandler()]; + yield [$fibonacciYJobDeferBefore]; + yield [$fibonacciYJobDefer, null, null, null, new DeferAsyncHandler()]; + yield [$fibonacciYJobDeferAfter, null, null, null, new DeferAsyncHandler()]; }, ['driver' => $driver]); -for ($i = 1; $i <= 5; $i++) { +for ($i = 5; $i <= 5; $i++) { $ip = new Ip(new YFlowData($i, $i)); $flow($ip); } From 9f64bf96dd737405bcb9677b9fe1be491077fa22 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Sat, 7 Sep 2024 17:40:48 +0200 Subject: [PATCH 05/14] :hammer: add fibonacci --- examples/yflow.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/yflow.php b/examples/yflow.php index 5a0a253e..ece58cf0 100644 --- a/examples/yflow.php +++ b/examples/yflow.php @@ -118,7 +118,7 @@ function factorialYMemo(int $n): int return new YFlowData($data->id, $data->number); }; -$factorialYJobDeferBefore = static function (YFlowData $data) use ($driver) { +$factorialYJobDeferBefore = static function (YFlowData $data) { printf("...*.. #%d - Job 4 : Calculating factorialYJobDefer(%d)\n", $data->id, $data->number); return new YFlowData($data->id, $data->number, $data->number); @@ -157,7 +157,7 @@ function factorialYMemo(int $n): int }); }; -$fibonacciYJobDeferBefore = static function (YFlowData $data) use ($driver) { +$fibonacciYJobDeferBefore = static function (YFlowData $data) { printf("....* #%d - Job 5 : Calculating fibonacciYJobDefer(%d)\n", $data->id, $data->number); return new YFlowData($data->id, $data->number, $data->number); @@ -174,9 +174,9 @@ function factorialYMemo(int $n): int $driver->delay($delay); $complete([new YFlowData($data->id, $data->number, 1), $defer]); } else { - $async($fibonacci([new YFlowData($data->id, $data->number, $data->result - 1), $defer]), function ($result1) use ($data, $complete, $driver, $async, $fibonacci, $defer) { + $async($fibonacci([new YFlowData($data->id, $data->number, $data->result - 1), $defer]), static function ($result1) use ($data, $complete, $driver, $async, $fibonacci) { [$resultData1, $defer1] = $result1; - $async($fibonacci([new YFlowData($data->id, $data->number, $data->result - 2), $defer1]), function ($result2) use ($data, $complete, $driver, $resultData1) { + $async($fibonacci([new YFlowData($data->id, $data->number, $data->result - 2), $defer1]), static function ($result2) use ($data, $complete, $driver, $resultData1) { [$resultData2, $defer2] = $result2; $delay = random_int(1, 3); printf("....* #%d - Job 5 : Step async fibonacciYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); @@ -200,7 +200,6 @@ function factorialYMemo(int $n): int }); }; - $flow = Flow::do(static function () use ( $factorialJob, $factorialYJobBefore, From c77e97e8633cf48a961de4fbc60662f8f309e020 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Sat, 7 Sep 2024 21:36:05 +0200 Subject: [PATCH 06/14] :bug: Fix FiberDriver --- examples/yflow.php | 10 +++++----- src/Driver/FiberDriver.php | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/examples/yflow.php b/examples/yflow.php index ece58cf0..6508a51f 100644 --- a/examples/yflow.php +++ b/examples/yflow.php @@ -119,7 +119,7 @@ function factorialYMemo(int $n): int }; $factorialYJobDeferBefore = static function (YFlowData $data) { - printf("...*.. #%d - Job 4 : Calculating factorialYJobDefer(%d)\n", $data->id, $data->number); + printf("...*. #%d - Job 4 : Calculating factorialYJobDefer(%d)\n", $data->id, $data->number); return new YFlowData($data->id, $data->number, $data->number); }; @@ -131,14 +131,14 @@ function factorialYMemo(int $n): int return $defer(static function ($complete, $async) use ($data, $defer, $factorial, $driver) { if ($data->result <= 1) { $delay = random_int(1, 3); - printf("...*.. #%d - Job 4 : Step factorialYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); + printf("...*. #%d - Job 4 : Step factorialYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); $driver->delay($delay); $complete([new YFlowData($data->id, $data->number, 1), $defer]); } else { $async($factorial([new YFlowData($data->id, $data->number, $data->result - 1), $defer]), static function ($result) use ($data, $complete, $driver) { [$resultData, $defer] = $result; $delay = random_int(1, 3); - printf("...*.. #%d - Job 4 : Step async factorialYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); + printf("...*. #%d - Job 4 : Step async factorialYJobDefer(%d) with delay %d\n", $data->id, $data->number, $delay); $driver->delay($delay); $complete([new YFlowData($data->id, $data->number, $data->result * $resultData->result), $defer]); }); @@ -151,7 +151,7 @@ function factorialYMemo(int $n): int [$data, $defer] = $args; return $defer(static function ($complete) use ($data, $defer) { - printf("...*.. #%d - Job 4 : Result for factorialYJobDefer(%d) = %d\n", $data->id, $data->number, $data->result); + printf("...*. #%d - Job 4 : Result for factorialYJobDefer(%d) = %d\n", $data->id, $data->number, $data->result); $complete([new YFlowData($data->id, $data->number), $defer]); }); @@ -226,7 +226,7 @@ function factorialYMemo(int $n): int yield [$fibonacciYJobDeferAfter, null, null, null, new DeferAsyncHandler()]; }, ['driver' => $driver]); -for ($i = 5; $i <= 5; $i++) { +for ($i = 1; $i <= 5; $i++) { $ip = new Ip(new YFlowData($i, $i)); $flow($ip); } diff --git a/src/Driver/FiberDriver.php b/src/Driver/FiberDriver.php index 2fdb3cef..0c08c2ba 100644 --- a/src/Driver/FiberDriver.php +++ b/src/Driver/FiberDriver.php @@ -99,15 +99,16 @@ public function await(array &$stream): void }; }; - $defer = static function ($isTick) { - return static function (Closure|JobInterface $job) use ($isTick) { - return static function (Closure $next) use ($isTick, $job) { + $defer = static function ($isTick) use (&$fiberDatas) { + return static function (Closure|JobInterface $job) use ($isTick, &$fiberDatas) { + return static function (Closure $next) use ($isTick, $job, &$fiberDatas) { $fiber = new Fiber(static function () use ($isTick, $job, $next) { try { $job(static function ($return) use ($isTick, $next) { if ($isTick === false) { $next($return); } + Fiber::suspend(); }, static function ($fn, $next) { $fn($next); }); @@ -117,6 +118,15 @@ public function await(array &$stream): void }); $fiber->start(); + + $fiberDatas[] = [ + 'fiber' => $fiber, + 'next' => static function ($return) {}, /*function ($return) use ($isTick, $next) { + if ($isTick === false) { + $next($return); + } + },*/ + ]; }; }; }; From 5e6d963f36e79b93220bc56fbdca7e620708f62f Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Sat, 7 Sep 2024 21:41:37 +0200 Subject: [PATCH 07/14] :fire: Call is not necessary --- src/Driver/FiberDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Driver/FiberDriver.php b/src/Driver/FiberDriver.php index 0c08c2ba..47cab5bd 100644 --- a/src/Driver/FiberDriver.php +++ b/src/Driver/FiberDriver.php @@ -108,7 +108,7 @@ public function await(array &$stream): void if ($isTick === false) { $next($return); } - Fiber::suspend(); + //Fiber::suspend(); }, static function ($fn, $next) { $fn($next); }); From 49e719306deb5fec8202616d5a58329f2419ac65 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Thu, 12 Sep 2024 00:35:13 +0200 Subject: [PATCH 08/14] :memo: Add await docs --- src/DriverInterface.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/DriverInterface.php b/src/DriverInterface.php index c33d16ad..ec368ce2 100644 --- a/src/DriverInterface.php +++ b/src/DriverInterface.php @@ -30,10 +30,13 @@ public function async(Closure|JobInterface $callback): Closure; public function defer(Closure $callback): mixed; /** - * @param array{'fnFlows': array, 'dispatchers': array} $stream + * Waits for all asynchronous operations in the stream to complete and rolls back to synchronous execution. + * + * @param array{'fnFlows': array, 'dispatchers': array} $stream The stream containing asynchronous operations to await */ public function await(array &$stream): void; + public function delay(float $seconds): void; /** From 8edbb62c54fb206ca4dbbd4e8d4871d6496afc2e Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Wed, 18 Sep 2024 01:33:30 +0200 Subject: [PATCH 09/14] :white_check_mark: Fix CI --- src/Driver/FiberDriver.php | 2 +- src/DriverInterface.php | 1 - tools/phpstan/composer.lock | 396 ++++++++++++++++++------------------ 3 files changed, 200 insertions(+), 199 deletions(-) diff --git a/src/Driver/FiberDriver.php b/src/Driver/FiberDriver.php index 47cab5bd..2ef97f53 100644 --- a/src/Driver/FiberDriver.php +++ b/src/Driver/FiberDriver.php @@ -108,7 +108,7 @@ public function await(array &$stream): void if ($isTick === false) { $next($return); } - //Fiber::suspend(); + // Fiber::suspend(); }, static function ($fn, $next) { $fn($next); }); diff --git a/src/DriverInterface.php b/src/DriverInterface.php index ec368ce2..be3b8db4 100644 --- a/src/DriverInterface.php +++ b/src/DriverInterface.php @@ -36,7 +36,6 @@ public function defer(Closure $callback): mixed; */ public function await(array &$stream): void; - public function delay(float $seconds): void; /** diff --git a/tools/phpstan/composer.lock b/tools/phpstan/composer.lock index d046e1be..e2d92f70 100644 --- a/tools/phpstan/composer.lock +++ b/tools/phpstan/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "465b0e63ca162f292e63dcba1bc58727", + "content-hash": "ae09737da70240630728f527576ca7f9", "packages": [ { "name": "psr/clock", @@ -106,16 +106,16 @@ }, { "name": "psr/log", - "version": "3.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -150,9 +150,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "symfony/clock", @@ -386,16 +386,16 @@ }, { "name": "symfony/messenger", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "604e182a7758ceea35921a8ad5dd492a6e13bae4" + "reference": "e1dc743492ff9f1cfb23e6eea3592bf2ec9bd079" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/604e182a7758ceea35921a8ad5dd492a6e13bae4", - "reference": "604e182a7758ceea35921a8ad5dd492a6e13bae4", + "url": "https://api.github.com/repos/symfony/messenger/zipball/e1dc743492ff9f1cfb23e6eea3592bf2ec9bd079", + "reference": "e1dc743492ff9f1cfb23e6eea3592bf2ec9bd079", "shasum": "" }, "require": { @@ -452,7 +452,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.1.3" + "source": "https://github.com/symfony/messenger/tree/v7.1.4" }, "funding": [ { @@ -468,24 +468,24 @@ "type": "tidelift" } ], - "time": "2024-07-09T19:36:07+00:00" + "time": "2024-08-06T14:26:51+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -528,7 +528,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" }, "funding": [ { @@ -544,7 +544,7 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:35:24+00:00" + "time": "2024-09-09T11:45:10+00:00" } ], "packages-dev": [ @@ -810,16 +810,16 @@ }, { "name": "doctrine/dbal", - "version": "3.8.6", + "version": "3.9.1", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "b7411825cf7efb7e51f9791dea19d86e43b399a1" + "reference": "d7dc08f98cba352b2bab5d32c5e58f7e745c11a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/b7411825cf7efb7e51f9791dea19d86e43b399a1", - "reference": "b7411825cf7efb7e51f9791dea19d86e43b399a1", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/d7dc08f98cba352b2bab5d32c5e58f7e745c11a7", + "reference": "d7dc08f98cba352b2bab5d32c5e58f7e745c11a7", "shasum": "" }, "require": { @@ -835,12 +835,12 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.11.5", + "phpstan/phpstan": "1.12.0", "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "9.6.19", + "phpunit/phpunit": "9.6.20", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.10.1", + "squizlabs/php_codesniffer": "3.10.2", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" @@ -903,7 +903,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.6" + "source": "https://github.com/doctrine/dbal/tree/3.9.1" }, "funding": [ { @@ -919,7 +919,7 @@ "type": "tidelift" } ], - "time": "2024-06-19T10:38:17+00:00" + "time": "2024-09-01T13:49:23+00:00" }, { "name": "doctrine/deprecations", @@ -970,16 +970,16 @@ }, { "name": "doctrine/doctrine-bundle", - "version": "2.12.0", + "version": "2.13.0", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "5418e811a14724068e95e0ba43353b903ada530f" + "reference": "ca59d84b8e63143ce1aed90cdb333ba329d71563" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/5418e811a14724068e95e0ba43353b903ada530f", - "reference": "5418e811a14724068e95e0ba43353b903ada530f", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/ca59d84b8e63143ce1aed90cdb333ba329d71563", + "reference": "ca59d84b8e63143ce1aed90cdb333ba329d71563", "shasum": "" }, "require": { @@ -1070,7 +1070,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.12.0" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.13.0" }, "funding": [ { @@ -1086,7 +1086,7 @@ "type": "tidelift" } ], - "time": "2024-03-19T07:20:37+00:00" + "time": "2024-09-01T09:46:40+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", @@ -1511,16 +1511,16 @@ }, { "name": "doctrine/migrations", - "version": "3.8.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c" + "reference": "7760fbd0b7cb58bfb50415505a7bab821adf0877" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/535a70dcbd88b8c6ba945be050977457f4f4c06c", - "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/7760fbd0b7cb58bfb50415505a7bab821adf0877", + "reference": "7760fbd0b7cb58bfb50415505a7bab821adf0877", "shasum": "" }, "require": { @@ -1543,6 +1543,7 @@ "doctrine/persistence": "^2 || ^3", "doctrine/sql-formatter": "^1.0", "ext-pdo_sqlite": "*", + "fig/log-test": "^1", "phpstan/phpstan": "^1.10", "phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-phpunit": "^1.3", @@ -1593,7 +1594,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.8.0" + "source": "https://github.com/doctrine/migrations/tree/3.8.1" }, "funding": [ { @@ -1609,20 +1610,20 @@ "type": "tidelift" } ], - "time": "2024-06-26T14:12:46+00:00" + "time": "2024-08-28T13:17:28+00:00" }, { "name": "doctrine/orm", - "version": "3.2.1", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "722cea6536775206e81744542b36fa7c9a4ea3e5" + "reference": "831a1eb7d260925528cdbb49cc1866c0357cf147" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/722cea6536775206e81744542b36fa7c9a4ea3e5", - "reference": "722cea6536775206e81744542b36fa7c9a4ea3e5", + "url": "https://api.github.com/repos/doctrine/orm/zipball/831a1eb7d260925528cdbb49cc1866c0357cf147", + "reference": "831a1eb7d260925528cdbb49cc1866c0357cf147", "shasum": "" }, "require": { @@ -1695,9 +1696,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.2.1" + "source": "https://github.com/doctrine/orm/tree/3.2.2" }, - "time": "2024-06-26T21:48:58+00:00" + "time": "2024-08-23T10:03:52+00:00" }, { "name": "doctrine/persistence", @@ -1853,26 +1854,27 @@ }, { "name": "laravel/serializable-closure", - "version": "v1.3.3", + "version": "v1.3.4", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "3dbf8a8e914634c48d389c1234552666b3d43754" + "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754", - "reference": "3dbf8a8e914634c48d389c1234552666b3d43754", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/61b87392d986dc49ad5ef64e75b1ff5fee24ef81", + "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81", "shasum": "" }, "require": { "php": "^7.3|^8.0" }, "require-dev": { - "nesbot/carbon": "^2.61", + "illuminate/support": "^8.0|^9.0|^10.0|^11.0", + "nesbot/carbon": "^2.61|^3.0", "pestphp/pest": "^1.21.3", "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11" + "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" }, "type": "library", "extra": { @@ -1909,7 +1911,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2023-11-08T14:08:06+00:00" + "time": "2024-08-02T07:48:17+00:00" }, { "name": "myclabs/deep-copy", @@ -1973,16 +1975,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.1.0", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", + "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", "shasum": "" }, "require": { @@ -2025,9 +2027,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.2.0" }, - "time": "2024-07-01T20:03:41+00:00" + "time": "2024-09-15T16:40:33+00:00" }, { "name": "openswoole/ide-helper", @@ -2188,16 +2190,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.11.9", + "version": "1.12.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e370bcddadaede0c1716338b262346f40d296f82" + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e370bcddadaede0c1716338b262346f40d296f82", - "reference": "e370bcddadaede0c1716338b262346f40d296f82", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0fcbf194ab63d8159bb70d9aa3e1350051632009", + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009", "shasum": "" }, "require": { @@ -2242,36 +2244,36 @@ "type": "github" } ], - "time": "2024-08-01T16:25:18+00:00" + "time": "2024-09-09T08:10:35+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.15", + "version": "10.1.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae" + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", - "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=8.1", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-text-template": "^3.0", - "sebastian/code-unit-reverse-lookup": "^3.0", - "sebastian/complexity": "^3.0", - "sebastian/environment": "^6.0", - "sebastian/lines-of-code": "^2.0", - "sebastian/version": "^4.0", - "theseer/tokenizer": "^1.2.0" + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { "phpunit/phpunit": "^10.1" @@ -2283,7 +2285,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1-dev" + "dev-main": "10.1.x-dev" } }, "autoload": { @@ -2312,7 +2314,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.15" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { @@ -2320,7 +2322,7 @@ "type": "github" } ], - "time": "2024-06-29T08:25:15+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2567,16 +2569,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.29", + "version": "10.5.34", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f" + "reference": "3c69d315bdf79080c8e115b69d1961c6905b0e18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e9e80872b4e8064401788ee8a32d40b4455318f", - "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3c69d315bdf79080c8e115b69d1961c6905b0e18", + "reference": "3c69d315bdf79080c8e115b69d1961c6905b0e18", "shasum": "" }, "require": { @@ -2590,14 +2592,14 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.15", + "phpunit/php-code-coverage": "^10.1.16", "phpunit/php-file-iterator": "^4.1.0", "phpunit/php-invoker": "^4.0.0", "phpunit/php-text-template": "^3.0.1", "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.1", + "sebastian/comparator": "^5.0.2", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", "sebastian/exporter": "^5.1.2", @@ -2648,7 +2650,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.29" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.34" }, "funding": [ { @@ -2664,7 +2666,7 @@ "type": "tidelift" } ], - "time": "2024-07-30T11:08:00+00:00" + "time": "2024-09-13T05:19:38+00:00" }, { "name": "psr/cache", @@ -3230,16 +3232,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372" + "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", "shasum": "" }, "require": { @@ -3250,7 +3252,7 @@ "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.3" + "phpunit/phpunit": "^10.4" }, "type": "library", "extra": { @@ -3295,7 +3297,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" }, "funding": [ { @@ -3303,7 +3305,7 @@ "type": "github" } ], - "time": "2023-08-14T13:18:12+00:00" + "time": "2024-08-12T06:03:08+00:00" }, { "name": "sebastian/complexity", @@ -4045,16 +4047,16 @@ }, { "name": "symfony/cache", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "8ac37acee794372f9732fe8a61a8221f6762148e" + "reference": "b61e464d7687bb7e8f677d5031c632bf3820df18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/8ac37acee794372f9732fe8a61a8221f6762148e", - "reference": "8ac37acee794372f9732fe8a61a8221f6762148e", + "url": "https://api.github.com/repos/symfony/cache/zipball/b61e464d7687bb7e8f677d5031c632bf3820df18", + "reference": "b61e464d7687bb7e8f677d5031c632bf3820df18", "shasum": "" }, "require": { @@ -4122,7 +4124,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.1.3" + "source": "https://github.com/symfony/cache/tree/v7.1.4" }, "funding": [ { @@ -4138,7 +4140,7 @@ "type": "tidelift" } ], - "time": "2024-07-17T06:10:24+00:00" + "time": "2024-08-12T09:59:40+00:00" }, { "name": "symfony/cache-contracts", @@ -4293,16 +4295,16 @@ }, { "name": "symfony/console", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9" + "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", - "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", + "url": "https://api.github.com/repos/symfony/console/zipball/1eed7af6961d763e7832e874d7f9b21c3ea9c111", + "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111", "shasum": "" }, "require": { @@ -4366,7 +4368,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.3" + "source": "https://github.com/symfony/console/tree/v7.1.4" }, "funding": [ { @@ -4382,20 +4384,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-08-15T22:48:53+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "8126f0be4ff984e4db0140e60917900a53facb49" + "reference": "5320e0bc2c9e2d7450bb4091e497a305a68b28ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/8126f0be4ff984e4db0140e60917900a53facb49", - "reference": "8126f0be4ff984e4db0140e60917900a53facb49", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5320e0bc2c9e2d7450bb4091e497a305a68b28ed", + "reference": "5320e0bc2c9e2d7450bb4091e497a305a68b28ed", "shasum": "" }, "require": { @@ -4446,7 +4448,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.1.3" + "source": "https://github.com/symfony/dependency-injection/tree/v7.1.4" }, "funding": [ { @@ -4462,7 +4464,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T07:35:39+00:00" + "time": "2024-08-29T08:16:25+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4533,16 +4535,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "b526822483124b62ff3cda14237418408f444e4d" + "reference": "5c31b278a52023970f4ef398e42ab9048483abfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/b526822483124b62ff3cda14237418408f444e4d", - "reference": "b526822483124b62ff3cda14237418408f444e4d", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/5c31b278a52023970f4ef398e42ab9048483abfa", + "reference": "5c31b278a52023970f4ef398e42ab9048483abfa", "shasum": "" }, "require": { @@ -4621,7 +4623,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.1.3" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.1.4" }, "funding": [ { @@ -4637,20 +4639,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-08-13T10:29:23+00:00" }, { "name": "symfony/doctrine-messenger", - "version": "v7.1.2", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-messenger.git", - "reference": "64e2195442df86a7a0c85a77162d0247601e9da9" + "reference": "7f2a9262d7af3f892e49382b918e991af2ae0738" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/64e2195442df86a7a0c85a77162d0247601e9da9", - "reference": "64e2195442df86a7a0c85a77162d0247601e9da9", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/7f2a9262d7af3f892e49382b918e991af2ae0738", + "reference": "7f2a9262d7af3f892e49382b918e991af2ae0738", "shasum": "" }, "require": { @@ -4693,7 +4695,7 @@ "description": "Symfony Doctrine Messenger Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-messenger/tree/v7.1.2" + "source": "https://github.com/symfony/doctrine-messenger/tree/v7.1.4" }, "funding": [ { @@ -4709,7 +4711,7 @@ "type": "tidelift" } ], - "time": "2024-06-20T15:47:37+00:00" + "time": "2024-08-30T07:19:54+00:00" }, { "name": "symfony/error-handler", @@ -4854,16 +4856,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "717c6329886f32dc65e27461f80f2a465412fdca" + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/717c6329886f32dc65e27461f80f2a465412fdca", - "reference": "717c6329886f32dc65e27461f80f2a465412fdca", + "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", "shasum": "" }, "require": { @@ -4898,7 +4900,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.3" + "source": "https://github.com/symfony/finder/tree/v7.1.4" }, "funding": [ { @@ -4914,20 +4916,20 @@ "type": "tidelift" } ], - "time": "2024-07-24T07:08:44+00:00" + "time": "2024-08-13T14:28:19+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "a32ec544bd501eb4619eb977860ad3076ee55061" + "reference": "711af4eefcb4054a9c93e44b403626e1826bcddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/a32ec544bd501eb4619eb977860ad3076ee55061", - "reference": "a32ec544bd501eb4619eb977860ad3076ee55061", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/711af4eefcb4054a9c93e44b403626e1826bcddd", + "reference": "711af4eefcb4054a9c93e44b403626e1826bcddd", "shasum": "" }, "require": { @@ -5045,7 +5047,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.1.3" + "source": "https://github.com/symfony/framework-bundle/tree/v7.1.4" }, "funding": [ { @@ -5061,7 +5063,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T13:24:34+00:00" + "time": "2024-08-11T16:10:02+00:00" }, { "name": "symfony/http-foundation", @@ -5142,16 +5144,16 @@ }, { "name": "symfony/http-kernel", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "db9702f3a04cc471ec8c70e881825db26ac5f186" + "reference": "6efcbd1b3f444f631c386504fc83eeca25963747" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/db9702f3a04cc471ec8c70e881825db26ac5f186", - "reference": "db9702f3a04cc471ec8c70e881825db26ac5f186", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6efcbd1b3f444f631c386504fc83eeca25963747", + "reference": "6efcbd1b3f444f631c386504fc83eeca25963747", "shasum": "" }, "require": { @@ -5236,7 +5238,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.4" }, "funding": [ { @@ -5252,7 +5254,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T14:58:15+00:00" + "time": "2024-08-30T17:02:28+00:00" }, { "name": "symfony/orm-pack", @@ -5305,20 +5307,20 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -5364,7 +5366,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -5380,24 +5382,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -5442,7 +5444,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -5458,24 +5460,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -5523,7 +5525,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -5539,24 +5541,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -5603,7 +5605,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -5619,24 +5621,24 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -5683,7 +5685,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -5699,7 +5701,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", @@ -5764,16 +5766,16 @@ }, { "name": "symfony/routing", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0" + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", - "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", + "url": "https://api.github.com/repos/symfony/routing/zipball/1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", "shasum": "" }, "require": { @@ -5825,7 +5827,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.3" + "source": "https://github.com/symfony/routing/tree/v7.1.4" }, "funding": [ { @@ -5841,7 +5843,7 @@ "type": "tidelift" } ], - "time": "2024-07-17T06:10:24+00:00" + "time": "2024-08-29T08:16:25+00:00" }, { "name": "symfony/service-contracts", @@ -5990,16 +5992,16 @@ }, { "name": "symfony/string", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ea272a882be7f20cad58d5d78c215001617b7f07" + "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ea272a882be7f20cad58d5d78c215001617b7f07", - "reference": "ea272a882be7f20cad58d5d78c215001617b7f07", + "url": "https://api.github.com/repos/symfony/string/zipball/6cd670a6d968eaeb1c77c2e76091c45c56bc367b", + "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b", "shasum": "" }, "require": { @@ -6057,7 +6059,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.3" + "source": "https://github.com/symfony/string/tree/v7.1.4" }, "funding": [ { @@ -6073,20 +6075,20 @@ "type": "tidelift" } ], - "time": "2024-07-22T10:25:37+00:00" + "time": "2024-08-12T09:59:40+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f" + "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/86af4617cca75a6e28598f49ae0690f3b9d4591f", - "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a5fa7481b199090964d6fd5dab6294d5a870c7aa", + "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa", "shasum": "" }, "require": { @@ -6140,7 +6142,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.4" }, "funding": [ { @@ -6156,7 +6158,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-08-30T16:12:47+00:00" }, { "name": "symfony/var-exporter", From aef7839eb255c202f0f3ad90bd7ad27eed4b41fa Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Thu, 17 Oct 2024 17:56:44 +0200 Subject: [PATCH 10/14] :ambulance: Symfony insight fix info --- .gitignore | 2 +- LICENSE | 2 +- docs/src/content/en/docs/getting-started/flow.md | 2 +- docs/src/content/en/docs/getting-started/ip-strategy.md | 2 +- docs/src/content/en/docs/getting-started/license.md | 2 +- docs/src/layouts/_default/section.sitemap.xml | 2 +- tools/.gitignore | 2 +- tools/phpcbf/phpcs.xml | 2 +- tools/phpcs/phpcs.xml | 2 +- tools/phpmd/phpmd.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 2ef07bd0..e68db33e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ # PHP /composer.lock -/vendor/ \ No newline at end of file +/vendor/ diff --git a/LICENSE b/LICENSE index 545ec31a..a948175b 100644 --- a/LICENSE +++ b/LICENSE @@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/docs/src/content/en/docs/getting-started/flow.md b/docs/src/content/en/docs/getting-started/flow.md index eb79a45c..729cd4bd 100644 --- a/docs/src/content/en/docs/getting-started/flow.md +++ b/docs/src/content/en/docs/getting-started/flow.md @@ -43,4 +43,4 @@ YFlow use YCombinator to provide recursion. ## Make your own Flow -You can make your custom Flow by implementing `Flow\FlowInterface`. \ No newline at end of file +You can make your custom Flow by implementing `Flow\FlowInterface`. diff --git a/docs/src/content/en/docs/getting-started/ip-strategy.md b/docs/src/content/en/docs/getting-started/ip-strategy.md index e960e07a..ccf5ded2 100644 --- a/docs/src/content/en/docs/getting-started/ip-strategy.md +++ b/docs/src/content/en/docs/getting-started/ip-strategy.md @@ -32,4 +32,4 @@ You can embed it by a custom strategy with is `LinearIpStrategy` by default. ## Make your Ip Strategy -You can make your custom Ip strategy by implementing `Flow\IpStrategyInterface` \ No newline at end of file +You can make your custom Ip strategy by implementing `Flow\IpStrategyInterface` diff --git a/docs/src/content/en/docs/getting-started/license.md b/docs/src/content/en/docs/getting-started/license.md index 80071989..641c91f8 100644 --- a/docs/src/content/en/docs/getting-started/license.md +++ b/docs/src/content/en/docs/getting-started/license.md @@ -32,4 +32,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/docs/src/layouts/_default/section.sitemap.xml b/docs/src/layouts/_default/section.sitemap.xml index 701951d6..afeebb8d 100644 --- a/docs/src/layouts/_default/section.sitemap.xml +++ b/docs/src/layouts/_default/section.sitemap.xml @@ -43,4 +43,4 @@ {{ end -}} {{ end -}} {{ end -}} - \ No newline at end of file + diff --git a/tools/.gitignore b/tools/.gitignore index 8a78ca5a..2d57ab66 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1 +1 @@ -/.castor.stub.php \ No newline at end of file +/.castor.stub.php diff --git a/tools/phpcbf/phpcs.xml b/tools/phpcbf/phpcs.xml index 535dc3ae..9952c9e5 100644 --- a/tools/phpcbf/phpcs.xml +++ b/tools/phpcbf/phpcs.xml @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/tools/phpcs/phpcs.xml b/tools/phpcs/phpcs.xml index 535dc3ae..9952c9e5 100644 --- a/tools/phpcs/phpcs.xml +++ b/tools/phpcs/phpcs.xml @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/tools/phpmd/phpmd.xml b/tools/phpmd/phpmd.xml index 56f4c07b..24047182 100644 --- a/tools/phpmd/phpmd.xml +++ b/tools/phpmd/phpmd.xml @@ -15,4 +15,4 @@ - \ No newline at end of file + From 72efcb300f30a4843da67de6d809329116345faf Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Thu, 17 Oct 2024 18:25:22 +0200 Subject: [PATCH 11/14] :ambulance: Symfony insight fix minor --- examples/Transport/Client.php | 44 +++ examples/client.php | 41 +- examples/yflow.php | 44 +-- src/Driver/AmpDriver.php | 4 +- src/Driver/FiberDriver.php | 3 +- src/Driver/ReactDriver.php | 4 +- src/Driver/SpatieDriver.php | 2 +- src/Driver/SwooleDriver.php | 2 +- tools/phpstan/composer.json | 4 +- tools/phpstan/composer.lock | 700 +++++++++++++++++----------------- 10 files changed, 430 insertions(+), 418 deletions(-) create mode 100644 examples/Transport/Client.php diff --git a/examples/Transport/Client.php b/examples/Transport/Client.php new file mode 100644 index 00000000..787cea09 --- /dev/null +++ b/examples/Transport/Client.php @@ -0,0 +1,44 @@ +sender->send($ip); + } + + /** + * @param callable[][]|HandlerDescriptor[][] $handlers + */ + public function wait(array $handlers): void + { + $bus = new MessageBus([ + new HandleMessageMiddleware(new HandlersLocator($handlers)), + ]); + $worker = new Worker(['transport' => $this->receiver], $bus); + $worker->run(); + } +} diff --git a/examples/client.php b/examples/client.php index 31a6e2ba..d40fe83b 100644 --- a/examples/client.php +++ b/examples/client.php @@ -5,45 +5,8 @@ require __DIR__ . '/../vendor/autoload.php'; use Doctrine\DBAL\DriverManager; +use Flow\Examples\Transport\Client; use Flow\Examples\Transport\DoctrineIpTransport; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\Handler\HandlerDescriptor; -use Symfony\Component\Messenger\Handler\HandlersLocator; -use Symfony\Component\Messenger\MessageBus; -use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware; -use Symfony\Component\Messenger\Stamp\DelayStamp; -use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface; -use Symfony\Component\Messenger\Transport\Sender\SenderInterface; -use Symfony\Component\Messenger\Worker; - -class client -{ - public function __construct( - private SenderInterface $sender, - private ReceiverInterface $receiver - ) {} - - /** - * @param ?int $delay The delay in milliseconds - */ - public function call(object $data, ?int $delay = null): void - { - $ip = Envelope::wrap($data, $delay ? [new DelayStamp($delay)] : []); - $this->sender->send($ip); - } - - /** - * @param callable[][]|HandlerDescriptor[][] $handlers - */ - public function wait(array $handlers): void - { - $bus = new MessageBus([ - new HandleMessageMiddleware(new HandlersLocator($handlers)), - ]); - $worker = new Worker(['transport' => $this->receiver], $bus); - $worker->run(); - } -} $connection = DriverManager::getConnection([ 'driver' => 'pdo_sqlite', @@ -51,7 +14,7 @@ public function wait(array $handlers): void ]); $transport = new DoctrineIpTransport($connection, uniqid('transport_', true)); -$client = new client($transport, $transport); +$client = new Client($transport, $transport); $ip = long2ip(random_int(ip2long('10.0.0.0'), ip2long('10.255.255.255'))); for ($i = 0; $i < 3; $i++) { diff --git a/examples/yflow.php b/examples/yflow.php index 6508a51f..a0d92a2c 100644 --- a/examples/yflow.php +++ b/examples/yflow.php @@ -26,23 +26,20 @@ }; printf("Use %s\n", $driver::class); -function factorial(int $n): int -{ - return ($n <= 1) ? 1 : $n * factorial($n - 1); -} +$factorial = static function (int $n) use (&$factorial): int { + return ($n <= 1) ? 1 : $n * $factorial($n - 1); +}; /** * @return JobInterface */ -function Ywrap(callable $func, callable $wrapperFunc): JobInterface -{ +$Ywrap = static function (callable $func, callable $wrapperFunc): JobInterface { $wrappedFunc = static fn ($recurse) => $wrapperFunc(static fn (...$args) => $func($recurse)(...$args)); return new YJob($wrappedFunc); -} +}; -function memoWrapperGenerator(callable $f): Closure -{ +$memoWrapperGenerator = static function (callable $f): Closure { static $cache = []; return static function ($y) use ($f, &$cache) { @@ -52,33 +49,30 @@ function memoWrapperGenerator(callable $f): Closure return $cache[$y]; }; -} +}; /** * @return JobInterface */ -function Ymemo(callable $f): JobInterface -{ - return Ywrap($f, 'memoWrapperGenerator'); -} +$Ymemo = static function (callable $f) use ($Ywrap, $memoWrapperGenerator): JobInterface { + return $Ywrap($f, $memoWrapperGenerator); +}; -function factorialGen(callable $func): Closure -{ +$factorialGen = static function (callable $func): Closure { return static function (int $n) use ($func): int { return ($n <= 1) ? 1 : $n * $func($n - 1); }; -} +}; -function factorialYMemo(int $n): int -{ - return Ymemo('factorialGen')($n); -} +$factorialYMemo = static function (int $n) use ($Ymemo, $factorialGen): int { + return $Ymemo($factorialGen)($n); +}; -$factorialJob = static function (YFlowData $data): YFlowData { +$factorialJob = static function (YFlowData $data) use ($factorial): YFlowData { printf("*.... #%d - Job 1 : Calculating factorial(%d)\n", $data->id, $data->number); // raw factorial calculation - $result = factorial($data->number); + $result = $factorial($data->number); printf("*.... #%d - Job 1 : Result for factorial(%d) = %d\n", $data->id, $data->number, $result); @@ -107,11 +101,11 @@ function factorialYMemo(int $n): int return new YFlowData($data->id, $data->number); }; -$factorialYMemoJob = static function (YFlowData $data) use ($driver): YFlowData { +$factorialYMemoJob = static function (YFlowData $data) use ($driver, $factorialYMemo): YFlowData { printf("..*.. #%d - Job 3 : Calculating factorialYMemo(%d)\n", $data->id, $data->number); $driver->delay(3); - $result = factorialYMemo($data->number); + $result = $factorialYMemo($data->number); printf("..*.. #%d - Job 3 : Result for factorialYMemo(%d) = %d\n", $data->id, $data->number, $result); diff --git a/src/Driver/AmpDriver.php b/src/Driver/AmpDriver.php index 14650814..6bc8ea3b 100644 --- a/src/Driver/AmpDriver.php +++ b/src/Driver/AmpDriver.php @@ -117,7 +117,7 @@ public function await(array &$stream): void $job = $stream['fnFlows'][$index]['job']; $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $job, $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + if ($data instanceof RuntimeException && array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); @@ -129,7 +129,7 @@ public function await(array &$stream): void } } - if ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0) { + if ($this->countIps($stream['dispatchers']) > 0 || $this->ticks > 0) { EventLoop::defer($loop); } else { EventLoop::getDriver()->stop(); diff --git a/src/Driver/FiberDriver.php b/src/Driver/FiberDriver.php index 2ef97f53..42f5af41 100644 --- a/src/Driver/FiberDriver.php +++ b/src/Driver/FiberDriver.php @@ -108,7 +108,6 @@ public function await(array &$stream): void if ($isTick === false) { $next($return); } - // Fiber::suspend(); }, static function ($fn, $next) { $fn($next); }); @@ -152,7 +151,7 @@ public function await(array &$stream): void }, static function (Closure|JobInterface $job) use ($defer) { return $defer(false)($job); }, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) and $stream['fnFlows'][$index]['errorJob'] !== null) { + if ($data instanceof RuntimeException && array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); diff --git a/src/Driver/ReactDriver.php b/src/Driver/ReactDriver.php index 96c21fb4..0cb6ba81 100644 --- a/src/Driver/ReactDriver.php +++ b/src/Driver/ReactDriver.php @@ -110,7 +110,7 @@ public function await(array &$stream): void $job = $stream['fnFlows'][$index]['job']; $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $job, $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + if ($data instanceof RuntimeException && array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); @@ -122,7 +122,7 @@ public function await(array &$stream): void } } - if ($this->countIps($stream['dispatchers']) > 0 or $this->ticks > 0) { + if ($this->countIps($stream['dispatchers']) > 0 || $this->ticks > 0) { $this->eventLoop->futureTick($loop); } else { $this->eventLoop->stop(); diff --git a/src/Driver/SpatieDriver.php b/src/Driver/SpatieDriver.php index 75d3c097..61765b3a 100644 --- a/src/Driver/SpatieDriver.php +++ b/src/Driver/SpatieDriver.php @@ -95,7 +95,7 @@ public function await(array &$stream): void $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); foreach ($nextIps as $nextIp) { $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + if ($data instanceof RuntimeException && array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); diff --git a/src/Driver/SwooleDriver.php b/src/Driver/SwooleDriver.php index 46340479..4b4fa75f 100644 --- a/src/Driver/SwooleDriver.php +++ b/src/Driver/SwooleDriver.php @@ -92,7 +92,7 @@ public function await(array &$stream): void $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); foreach ($nextIps as $nextIp) { $stream['dispatchers'][$index]->dispatch(new AsyncEvent($async, $defer, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { - if ($data instanceof RuntimeException and array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + if ($data instanceof RuntimeException && array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { $stream['fnFlows'][$index]['errorJob']($data); } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { $ip = new Ip($data); diff --git a/tools/phpstan/composer.json b/tools/phpstan/composer.json index b0db540c..a90b5642 100644 --- a/tools/phpstan/composer.json +++ b/tools/phpstan/composer.json @@ -7,8 +7,8 @@ "require-dev": { "amphp/amp": "^3.0", "openswoole/ide-helper": "^22.1.5", - "phpstan/phpstan": "^1.11", - "phpunit/phpunit": "^10.3", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^11.4", "react/async": "^4.3", "spatie/async": "^1.6", "symfony/doctrine-messenger": "^7.0", diff --git a/tools/phpstan/composer.lock b/tools/phpstan/composer.lock index e2d92f70..3dc228ae 100644 --- a/tools/phpstan/composer.lock +++ b/tools/phpstan/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ae09737da70240630728f527576ca7f9", + "content-hash": "250dd2dd03dfe2e446c3aa0aa41fe5e0", "packages": [ { "name": "psr/clock", @@ -386,16 +386,16 @@ }, { "name": "symfony/messenger", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "e1dc743492ff9f1cfb23e6eea3592bf2ec9bd079" + "reference": "e1c0ced845e3dac12ab428c5ed42dbe7a58ca576" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/e1dc743492ff9f1cfb23e6eea3592bf2ec9bd079", - "reference": "e1dc743492ff9f1cfb23e6eea3592bf2ec9bd079", + "url": "https://api.github.com/repos/symfony/messenger/zipball/e1c0ced845e3dac12ab428c5ed42dbe7a58ca576", + "reference": "e1c0ced845e3dac12ab428c5ed42dbe7a58ca576", "shasum": "" }, "require": { @@ -452,7 +452,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.1.4" + "source": "https://github.com/symfony/messenger/tree/v7.1.5" }, "funding": [ { @@ -468,7 +468,7 @@ "type": "tidelift" } ], - "time": "2024-08-06T14:26:51+00:00" + "time": "2024-09-08T12:32:26+00:00" }, { "name": "symfony/polyfill-php83", @@ -810,16 +810,16 @@ }, { "name": "doctrine/dbal", - "version": "3.9.1", + "version": "3.9.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "d7dc08f98cba352b2bab5d32c5e58f7e745c11a7" + "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/d7dc08f98cba352b2bab5d32c5e58f7e745c11a7", - "reference": "d7dc08f98cba352b2bab5d32c5e58f7e745c11a7", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", + "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", "shasum": "" }, "require": { @@ -835,7 +835,7 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.12.0", + "phpstan/phpstan": "1.12.6", "phpstan/phpstan-strict-rules": "^1.6", "phpunit/phpunit": "9.6.20", "psalm/plugin-phpunit": "0.18.4", @@ -903,7 +903,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.9.1" + "source": "https://github.com/doctrine/dbal/tree/3.9.3" }, "funding": [ { @@ -919,7 +919,7 @@ "type": "tidelift" } ], - "time": "2024-09-01T13:49:23+00:00" + "time": "2024-10-10T17:56:43+00:00" }, { "name": "doctrine/deprecations", @@ -1511,16 +1511,16 @@ }, { "name": "doctrine/migrations", - "version": "3.8.1", + "version": "3.8.2", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "7760fbd0b7cb58bfb50415505a7bab821adf0877" + "reference": "5007eb1168691225ac305fe16856755c20860842" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/7760fbd0b7cb58bfb50415505a7bab821adf0877", - "reference": "7760fbd0b7cb58bfb50415505a7bab821adf0877", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/5007eb1168691225ac305fe16856755c20860842", + "reference": "5007eb1168691225ac305fe16856755c20860842", "shasum": "" }, "require": { @@ -1594,7 +1594,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.8.1" + "source": "https://github.com/doctrine/migrations/tree/3.8.2" }, "funding": [ { @@ -1610,20 +1610,20 @@ "type": "tidelift" } ], - "time": "2024-08-28T13:17:28+00:00" + "time": "2024-10-10T21:35:27+00:00" }, { "name": "doctrine/orm", - "version": "3.2.2", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "831a1eb7d260925528cdbb49cc1866c0357cf147" + "reference": "69958152e661aa9c14e80d1ee4962863485aa60b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/831a1eb7d260925528cdbb49cc1866c0357cf147", - "reference": "831a1eb7d260925528cdbb49cc1866c0357cf147", + "url": "https://api.github.com/repos/doctrine/orm/zipball/69958152e661aa9c14e80d1ee4962863485aa60b", + "reference": "69958152e661aa9c14e80d1ee4962863485aa60b", "shasum": "" }, "require": { @@ -1645,7 +1645,10 @@ "require-dev": { "doctrine/coding-standard": "^12.0", "phpbench/phpbench": "^1.0", - "phpstan/phpstan": "1.11.1", + "phpdocumentor/guides-cli": "^1.4", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "1.12.6", + "phpstan/phpstan-deprecation-rules": "^1.2", "phpunit/phpunit": "^10.4.0", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.2", @@ -1696,9 +1699,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.2.2" + "source": "https://github.com/doctrine/orm/tree/3.3.0" }, - "time": "2024-08-23T10:03:52+00:00" + "time": "2024-10-12T20:07:18+00:00" }, { "name": "doctrine/persistence", @@ -1799,16 +1802,16 @@ }, { "name": "doctrine/sql-formatter", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "7f83911cc5eba870de7ebb11283972483f7e2891" + "reference": "16ca9e39877369d664f06dacde468548298bdc40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/7f83911cc5eba870de7ebb11283972483f7e2891", - "reference": "7f83911cc5eba870de7ebb11283972483f7e2891", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/16ca9e39877369d664f06dacde468548298bdc40", + "reference": "16ca9e39877369d664f06dacde468548298bdc40", "shasum": "" }, "require": { @@ -1816,6 +1819,7 @@ }, "require-dev": { "doctrine/coding-standard": "^12", + "ergebnis/phpunit-slow-test-detector": "^2.14", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^10.5", "vimeo/psalm": "^5.24" @@ -1848,22 +1852,22 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.4.1" + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.0" }, - "time": "2024-08-05T20:32:22+00:00" + "time": "2024-09-11T07:29:40+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.3.4", + "version": "v1.3.5", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81" + "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/61b87392d986dc49ad5ef64e75b1ff5fee24ef81", - "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", + "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", "shasum": "" }, "require": { @@ -1911,7 +1915,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-08-02T07:48:17+00:00" + "time": "2024-09-23T13:33:08+00:00" }, { "name": "myclabs/deep-copy", @@ -1975,16 +1979,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.2.0", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", - "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { @@ -2027,9 +2031,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.2.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2024-09-15T16:40:33+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "openswoole/ide-helper", @@ -2190,16 +2194,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.3", + "version": "1.12.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009" + "reference": "dc4d2f145a88ea7141ae698effd64d9df46527ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0fcbf194ab63d8159bb70d9aa3e1350051632009", - "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc4d2f145a88ea7141ae698effd64d9df46527ae", + "reference": "dc4d2f145a88ea7141ae698effd64d9df46527ae", "shasum": "" }, "require": { @@ -2244,39 +2248,39 @@ "type": "github" } ], - "time": "2024-09-09T08:10:35+00:00" + "time": "2024-10-06T15:03:59+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.16", + "version": "11.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", + "nikic/php-parser": "^5.3.1", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^10.1" + "phpunit/phpunit": "^11.4.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -2285,7 +2289,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1.x-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -2314,7 +2318,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" }, "funding": [ { @@ -2322,32 +2326,32 @@ "type": "github" } ], - "time": "2024-08-22T04:31:57+00:00" + "time": "2024-10-09T06:21:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.1.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -2375,7 +2379,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -2383,28 +2387,28 @@ "type": "github" } ], - "time": "2023-08-31T06:24:48+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { "name": "phpunit/php-invoker", - "version": "4.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" @@ -2412,7 +2416,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -2438,7 +2442,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -2446,32 +2451,32 @@ "type": "github" } ], - "time": "2023-02-03T06:56:09+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -2498,7 +2503,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -2506,32 +2511,32 @@ "type": "github" } ], - "time": "2023-08-31T14:07:24+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "6.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -2557,7 +2562,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -2565,20 +2571,20 @@ "type": "github" } ], - "time": "2023-02-03T06:57:52+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "10.5.34", + "version": "11.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3c69d315bdf79080c8e115b69d1961c6905b0e18" + "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3c69d315bdf79080c8e115b69d1961c6905b0e18", - "reference": "3c69d315bdf79080c8e115b69d1961c6905b0e18", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7875627f15f4da7e7f0823d1f323f7295a77334e", + "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e", "shasum": "" }, "require": { @@ -2591,23 +2597,22 @@ "myclabs/deep-copy": "^1.12.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.2", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.2", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.0", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.6", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.1", + "sebastian/comparator": "^6.1.0", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.1.3", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.0", + "sebastian/version": "^5.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -2618,7 +2623,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "11.4-dev" } }, "autoload": { @@ -2650,7 +2655,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.34" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.1" }, "funding": [ { @@ -2666,7 +2671,7 @@ "type": "tidelift" } ], - "time": "2024-09-13T05:19:38+00:00" + "time": "2024-10-08T15:38:37+00:00" }, { "name": "psr/cache", @@ -3064,28 +3069,28 @@ }, { "name": "sebastian/cli-parser", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3109,7 +3114,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -3117,32 +3122,32 @@ "type": "github" } ], - "time": "2024-03-02T07:12:49+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", - "version": "2.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3165,7 +3170,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" }, "funding": [ { @@ -3173,32 +3179,32 @@ "type": "github" } ], - "time": "2023-02-03T06:58:43+00:00" + "time": "2024-07-03T04:44:28+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -3220,7 +3226,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -3228,36 +3235,36 @@ "type": "github" } ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", - "version": "5.0.2", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" + "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa37b9e2ca618cb051d71b60120952ee8ca8b03d", + "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.4" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -3297,7 +3304,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.1.0" }, "funding": [ { @@ -3305,33 +3312,33 @@ "type": "github" } ], - "time": "2024-08-12T06:03:08+00:00" + "time": "2024-09-11T15:42:56+00:00" }, { "name": "sebastian/complexity", - "version": "3.2.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -3355,7 +3362,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -3363,33 +3370,33 @@ "type": "github" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "5.1.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -3422,7 +3429,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -3430,27 +3437,27 @@ "type": "github" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "6.1.0", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-posix": "*" @@ -3458,7 +3465,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -3486,7 +3493,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" }, "funding": [ { @@ -3494,34 +3501,34 @@ "type": "github" } ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2024-07-03T04:54:44+00:00" }, { "name": "sebastian/exporter", - "version": "5.1.2", + "version": "6.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -3564,7 +3571,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" }, "funding": [ { @@ -3572,35 +3579,35 @@ "type": "github" } ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2024-07-03T04:56:19+00:00" }, { "name": "sebastian/global-state", - "version": "6.0.2", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -3626,7 +3633,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -3634,33 +3641,33 @@ "type": "github" } ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "2.0.2", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3684,7 +3691,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -3692,34 +3699,34 @@ "type": "github" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "5.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -3741,7 +3748,8 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -3749,32 +3757,32 @@ "type": "github" } ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -3796,7 +3804,8 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -3804,32 +3813,32 @@ "type": "github" } ], - "time": "2023-02-03T07:06:18+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "5.0.0", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -3859,7 +3868,8 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { @@ -3867,32 +3877,32 @@ "type": "github" } ], - "time": "2023-02-03T07:05:40+00:00" + "time": "2024-07-03T05:10:34+00:00" }, { "name": "sebastian/type", - "version": "4.0.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -3915,7 +3925,8 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" }, "funding": [ { @@ -3923,29 +3934,29 @@ "type": "github" } ], - "time": "2023-02-03T07:10:45+00:00" + "time": "2024-09-17T13:12:04+00:00" }, { "name": "sebastian/version", - "version": "4.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -3968,7 +3979,8 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -3976,7 +3988,7 @@ "type": "github" } ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { "name": "spatie/async", @@ -4047,16 +4059,16 @@ }, { "name": "symfony/cache", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "b61e464d7687bb7e8f677d5031c632bf3820df18" + "reference": "86e5296b10e4dec8c8441056ca606aedb8a3be0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/b61e464d7687bb7e8f677d5031c632bf3820df18", - "reference": "b61e464d7687bb7e8f677d5031c632bf3820df18", + "url": "https://api.github.com/repos/symfony/cache/zipball/86e5296b10e4dec8c8441056ca606aedb8a3be0a", + "reference": "86e5296b10e4dec8c8441056ca606aedb8a3be0a", "shasum": "" }, "require": { @@ -4124,7 +4136,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.1.4" + "source": "https://github.com/symfony/cache/tree/v7.1.5" }, "funding": [ { @@ -4140,7 +4152,7 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:59:40+00:00" + "time": "2024-09-17T09:16:35+00:00" }, { "name": "symfony/cache-contracts", @@ -4295,16 +4307,16 @@ }, { "name": "symfony/console", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111" + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1eed7af6961d763e7832e874d7f9b21c3ea9c111", - "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111", + "url": "https://api.github.com/repos/symfony/console/zipball/0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee", "shasum": "" }, "require": { @@ -4368,7 +4380,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.4" + "source": "https://github.com/symfony/console/tree/v7.1.5" }, "funding": [ { @@ -4384,20 +4396,20 @@ "type": "tidelift" } ], - "time": "2024-08-15T22:48:53+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "5320e0bc2c9e2d7450bb4091e497a305a68b28ed" + "reference": "38465f925ec4e0707b090e9147c65869837d639d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5320e0bc2c9e2d7450bb4091e497a305a68b28ed", - "reference": "5320e0bc2c9e2d7450bb4091e497a305a68b28ed", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/38465f925ec4e0707b090e9147c65869837d639d", + "reference": "38465f925ec4e0707b090e9147c65869837d639d", "shasum": "" }, "require": { @@ -4448,7 +4460,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.1.4" + "source": "https://github.com/symfony/dependency-injection/tree/v7.1.5" }, "funding": [ { @@ -4464,7 +4476,7 @@ "type": "tidelift" } ], - "time": "2024-08-29T08:16:25+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4535,16 +4547,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "5c31b278a52023970f4ef398e42ab9048483abfa" + "reference": "2568d0adaa5b0018b07beaa90363b880a43cc957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/5c31b278a52023970f4ef398e42ab9048483abfa", - "reference": "5c31b278a52023970f4ef398e42ab9048483abfa", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/2568d0adaa5b0018b07beaa90363b880a43cc957", + "reference": "2568d0adaa5b0018b07beaa90363b880a43cc957", "shasum": "" }, "require": { @@ -4623,7 +4635,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.1.4" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.1.5" }, "funding": [ { @@ -4639,20 +4651,20 @@ "type": "tidelift" } ], - "time": "2024-08-13T10:29:23+00:00" + "time": "2024-09-08T12:32:26+00:00" }, { "name": "symfony/doctrine-messenger", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-messenger.git", - "reference": "7f2a9262d7af3f892e49382b918e991af2ae0738" + "reference": "29015027fb63461e035246e07d74eeab9cb03304" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/7f2a9262d7af3f892e49382b918e991af2ae0738", - "reference": "7f2a9262d7af3f892e49382b918e991af2ae0738", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/29015027fb63461e035246e07d74eeab9cb03304", + "reference": "29015027fb63461e035246e07d74eeab9cb03304", "shasum": "" }, "require": { @@ -4695,7 +4707,7 @@ "description": "Symfony Doctrine Messenger Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-messenger/tree/v7.1.4" + "source": "https://github.com/symfony/doctrine-messenger/tree/v7.1.5" }, "funding": [ { @@ -4711,7 +4723,7 @@ "type": "tidelift" } ], - "time": "2024-08-30T07:19:54+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/error-handler", @@ -4790,16 +4802,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.1.2", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/61fe0566189bf32e8cfee78335d8776f64a66f5a", + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a", "shasum": "" }, "require": { @@ -4836,7 +4848,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.2" + "source": "https://github.com/symfony/filesystem/tree/v7.1.5" }, "funding": [ { @@ -4852,7 +4864,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-09-17T09:16:35+00:00" }, { "name": "symfony/finder", @@ -4920,16 +4932,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "711af4eefcb4054a9c93e44b403626e1826bcddd" + "reference": "8a792de86230c13a9de7750c0c8b23cc083183d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/711af4eefcb4054a9c93e44b403626e1826bcddd", - "reference": "711af4eefcb4054a9c93e44b403626e1826bcddd", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/8a792de86230c13a9de7750c0c8b23cc083183d4", + "reference": "8a792de86230c13a9de7750c0c8b23cc083183d4", "shasum": "" }, "require": { @@ -4938,7 +4950,7 @@ "php": ">=8.2", "symfony/cache": "^6.4|^7.0", "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^7.1", + "symfony/dependency-injection": "^7.1.5", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.4|^7.0", "symfony/event-dispatcher": "^6.4|^7.0", @@ -5047,7 +5059,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.1.4" + "source": "https://github.com/symfony/framework-bundle/tree/v7.1.5" }, "funding": [ { @@ -5063,20 +5075,20 @@ "type": "tidelift" } ], - "time": "2024-08-11T16:10:02+00:00" + "time": "2024-09-20T13:35:23+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.1.3", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f602d5c17d1fa02f8019ace2687d9d136b7f4a1a" + "reference": "e30ef73b1e44eea7eb37ba69600a354e553f694b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f602d5c17d1fa02f8019ace2687d9d136b7f4a1a", - "reference": "f602d5c17d1fa02f8019ace2687d9d136b7f4a1a", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e30ef73b1e44eea7eb37ba69600a354e553f694b", + "reference": "e30ef73b1e44eea7eb37ba69600a354e553f694b", "shasum": "" }, "require": { @@ -5124,7 +5136,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.1.3" + "source": "https://github.com/symfony/http-foundation/tree/v7.1.5" }, "funding": [ { @@ -5140,20 +5152,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "6efcbd1b3f444f631c386504fc83eeca25963747" + "reference": "44204d96150a9df1fc57601ec933d23fefc2d65b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6efcbd1b3f444f631c386504fc83eeca25963747", - "reference": "6efcbd1b3f444f631c386504fc83eeca25963747", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/44204d96150a9df1fc57601ec933d23fefc2d65b", + "reference": "44204d96150a9df1fc57601ec933d23fefc2d65b", "shasum": "" }, "require": { @@ -5238,7 +5250,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.4" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.5" }, "funding": [ { @@ -5254,7 +5266,7 @@ "type": "tidelift" } ], - "time": "2024-08-30T17:02:28+00:00" + "time": "2024-09-21T06:09:21+00:00" }, { "name": "symfony/orm-pack", @@ -5705,16 +5717,16 @@ }, { "name": "symfony/process", - "version": "v7.1.3", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca" + "reference": "5c03ee6369281177f07f7c68252a280beccba847" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/7f2f542c668ad6c313dc4a5e9c3321f733197eca", - "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca", + "url": "https://api.github.com/repos/symfony/process/zipball/5c03ee6369281177f07f7c68252a280beccba847", + "reference": "5c03ee6369281177f07f7c68252a280beccba847", "shasum": "" }, "require": { @@ -5746,7 +5758,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.3" + "source": "https://github.com/symfony/process/tree/v7.1.5" }, "funding": [ { @@ -5762,7 +5774,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:44:47+00:00" + "time": "2024-09-19T21:48:23+00:00" }, { "name": "symfony/routing", @@ -5992,16 +6004,16 @@ }, { "name": "symfony/string", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b" + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/6cd670a6d968eaeb1c77c2e76091c45c56bc367b", - "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b", + "url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306", + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306", "shasum": "" }, "require": { @@ -6059,7 +6071,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.4" + "source": "https://github.com/symfony/string/tree/v7.1.5" }, "funding": [ { @@ -6075,20 +6087,20 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:59:40+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.4", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa" + "reference": "e20e03889539fd4e4211e14d2179226c513c010d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a5fa7481b199090964d6fd5dab6294d5a870c7aa", - "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e20e03889539fd4e4211e14d2179226c513c010d", + "reference": "e20e03889539fd4e4211e14d2179226c513c010d", "shasum": "" }, "require": { @@ -6142,7 +6154,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.4" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.5" }, "funding": [ { @@ -6158,7 +6170,7 @@ "type": "tidelift" } ], - "time": "2024-08-30T16:12:47+00:00" + "time": "2024-09-16T10:07:02+00:00" }, { "name": "symfony/var-exporter", @@ -6296,5 +6308,5 @@ "php": ">=8.3" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From e6c5794354cdac38e57d73c4097940d3ed52bf19 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Sun, 27 Oct 2024 13:43:55 +0100 Subject: [PATCH 12/14] :recycle: Update Flow:do to FlowFactory:create --- CHANGELOG.md | 1 + README.md | 3 +- examples/flow.php | 4 +- examples/server.php | 4 +- examples/yflow.php | 4 +- src/Flow/Flow.php | 92 +--------------------- src/Flow/FlowDecorator.php | 5 -- src/FlowFactory.php | 156 +++++++++++++++++++++++++++++++++++++ src/FlowInterface.php | 44 ----------- tests/Flow/FlowTest.php | 3 +- 10 files changed, 169 insertions(+), 147 deletions(-) create mode 100644 src/FlowFactory.php diff --git a/CHANGELOG.md b/CHANGELOG.md index f2e8e89a..378b8e1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Add event Event::POOL occurs when Flow needs to count IPs to process. - Add `Flow\IpPool` for managing pools of Ips. - Update `Flow\Event\PullEvent` to pull multiple Ips instead one. +- Move `Flow::do` to `FlowFactory::create` ## v1.2.2 diff --git a/README.md b/README.md index 03399db5..8d648bc8 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ composer require darkwood/flow create(static function() { yield fn (D1 $data1) => new D2($data1->n1 += 1); yield fn (D2 $data2) => new D3($data2->n2 * 2); yield function(D3 $data3) { diff --git a/examples/flow.php b/examples/flow.php index 63fb476e..d49ee947 100644 --- a/examples/flow.php +++ b/examples/flow.php @@ -14,7 +14,7 @@ use Flow\Examples\Model\DataC; use Flow\Examples\Model\DataD; use Flow\ExceptionInterface; -use Flow\Flow\Flow; +use Flow\FlowFactory; use Flow\Ip; use Flow\IpStrategy\MaxIpStrategy; use Flow\Job\ClosureJob; @@ -92,7 +92,7 @@ $asyncTask = static function ($job1, $job2, $job3, $errorJob1, $errorJob2, $driver) { echo "begin - flow asynchronous\n"; - $flow = Flow::do(static function () use ($job1, $job2, $job3, $errorJob1, $errorJob2) { + $flow = (new FlowFactory())->create(static function () use ($job1, $job2, $job3, $errorJob1, $errorJob2) { yield [$job1, $errorJob1, new MaxIpStrategy(2)]; yield [$job2, $errorJob2, new MaxIpStrategy(2)]; yield $job3; diff --git a/examples/server.php b/examples/server.php index 3c3375f0..6bea6c0f 100644 --- a/examples/server.php +++ b/examples/server.php @@ -12,8 +12,8 @@ use Flow\Driver\SwooleDriver; use Flow\Examples\Transport\DoctrineIpTransport; use Flow\ExceptionInterface; -use Flow\Flow\Flow; use Flow\Flow\TransportFlow; +use Flow\FlowFactory; use Flow\Ip; use Flow\IpStrategy\MaxIpStrategy; use Symfony\Component\Messenger\Envelope; @@ -74,7 +74,7 @@ printf("%s\n", $exception->getMessage()); }; -$flow = Flow::do(static function () use ($addOneJob, $multbyTwoJob, $minusThreeJob, $errorJob) { +$flow = (new FlowFactory())->create(static function () use ($addOneJob, $multbyTwoJob, $minusThreeJob, $errorJob) { yield [$addOneJob, $errorJob, new MaxIpStrategy(1)]; yield [$multbyTwoJob, $errorJob, new MaxIpStrategy(3)]; yield [$minusThreeJob, $errorJob, new MaxIpStrategy(2)]; diff --git a/examples/yflow.php b/examples/yflow.php index a0d92a2c..ef53b703 100644 --- a/examples/yflow.php +++ b/examples/yflow.php @@ -11,8 +11,8 @@ use Flow\Driver\SpatieDriver; use Flow\Driver\SwooleDriver; use Flow\Examples\Model\YFlowData; -use Flow\Flow\Flow; use Flow\Flow\YFlow; +use Flow\FlowFactory; use Flow\Ip; use Flow\Job\YJob; use Flow\JobInterface; @@ -194,7 +194,7 @@ }); }; -$flow = Flow::do(static function () use ( +$flow = (new FlowFactory())->create(static function () use ( $factorialJob, $factorialYJobBefore, $factorialYJob, diff --git a/src/Flow/Flow.php b/src/Flow/Flow.php index a5f588fc..5730fad0 100644 --- a/src/Flow/Flow.php +++ b/src/Flow/Flow.php @@ -11,20 +11,16 @@ use Flow\DriverInterface; use Flow\Event; use Flow\Event\PushEvent; -use Flow\Exception\LogicException; use Flow\ExceptionInterface; +use Flow\FlowFactory; use Flow\FlowInterface; use Flow\Ip; use Flow\IpStrategy\LinearIpStrategy; use Flow\IpStrategyInterface; use Flow\JobInterface; -use Generator; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use function array_key_exists; -use function is_array; - /** * @template T1 * @template T2 @@ -91,38 +87,9 @@ public function __invoke(Ip $ip): void $this->stream['dispatchers'][0]->dispatch(new PushEvent($ip), Event::PUSH); } - public static function do(callable $callable, ?array $config = null): FlowInterface - { - /** - * @var Closure|Generator $generator - */ - $generator = $callable(); - - if ($generator instanceof Generator) { - $flows = []; - - while ($generator->valid()) { - $flow = self::flowUnwrap($generator->current(), $config); - - $generator->send($flow); - - $flows[] = $flow; - } - - $return = $generator->getReturn(); - if (!empty($return)) { - $flows[] = self::flowUnwrap($return, $config); - } - - return self::flowMap($flows); - } - - return self::flowUnwrap($generator, $config); - } - public function fn(array|Closure|FlowInterface|JobInterface $flow): FlowInterface { - $flow = self::flowUnwrap($flow, ['driver' => $this->driver]); + $flow = (new FlowFactory($this->driver))->createFlow($flow); $this->stream['fnFlows'][] = [ 'job' => $flow->job, @@ -137,59 +104,4 @@ public function await(): void { $this->driver->await($this->stream); } - - /** - * @param array|Closure|FlowInterface $flow - * @param ?array $config - * - * @return Flow - * - * #param ?array{ - * 0: Closure, - * 1?: Closure, - * 2?: IpStrategyInterface, - * 3?: EventDispatcherInterface, - * 4?: AsyncHandlerInterface, - * 5?: DriverInterface - * }|array{ - * "ipStrategy"?: IpStrategyInterface, - * "dispatcher"?: EventDispatcherInterface, - * "asyncHandler"?: AsyncHandlerInterface, - * "driver"?: DriverInterface - * } $config - */ - private static function flowUnwrap($flow, ?array $config = null): FlowInterface - { - if ($flow instanceof Closure || $flow instanceof JobInterface) { - return new self(...[...['job' => $flow], ...($config ?? [])]); - } - if (is_array($flow)) { - if (array_key_exists(0, $flow) || array_key_exists('job', $flow)) { - return new self(...[...$flow, ...($config ?? [])]); - } - - return self::flowMap($flow); - } - - return $flow; - } - - /** - * @param array> $flows - * - * @return FlowInterface - */ - private static function flowMap(array $flows) - { - $flow = array_shift($flows); - if (null === $flow) { - throw new LogicException('Flow is empty'); - } - - foreach ($flows as $flowIt) { - $flow = $flow->fn($flowIt); - } - - return $flow; - } } diff --git a/src/Flow/FlowDecorator.php b/src/Flow/FlowDecorator.php index f91e7bb3..72d335f8 100644 --- a/src/Flow/FlowDecorator.php +++ b/src/Flow/FlowDecorator.php @@ -32,11 +32,6 @@ public function fn(array|Closure|FlowInterface|JobInterface $flow): FlowInterfac return $this->flow->fn($flow); } - public static function do(callable $callable, ?array $config = null): FlowInterface - { - return Flow::do($callable, $config); - } - public function await(): void { $this->flow->await(); diff --git a/src/FlowFactory.php b/src/FlowFactory.php new file mode 100644 index 00000000..82ca7a38 --- /dev/null +++ b/src/FlowFactory.php @@ -0,0 +1,156 @@ + $driver + */ + public function __construct( + private ?DriverInterface $driver = null + ) {} + + /** + * Do-notation a.k.a. for-comprehension. + * + * Syntax sugar for sequential {@see FlowInterface::fn()} calls + * + * Syntax "$flow = yield $wrapedFlow" mean: + * 1) $wrapedFlow can be Closure as Job, array constructor arguments for Flow instanciation, array configuration for Flow instanciation or FlowInterface instance + * 2) $flow is assigned as FlowInterface instance + * 3) optionnaly you can return another wrapedFlow + * + * ```php + * $flow = (new FlowFactory())->create(static function() { + * yield new Flow(fn($a) => $a + 1); + * $flow = yield fn($b) => $b * 2; + * $flow = yield $flow->fn([fn($c) => $c * 4]) + * return [$flow, [fn($d) => $d - 8]]; + * }); + * ``` + * $config if provided will be the fallback array configuration for Flow instanciation + * + * @param callable(): Generator|Closure $callable + * @param ?array $config + * + * #param ?array{ + * 0: Closure|array, + * 1?: Closure|array, + * 2?: IpStrategyInterface, + * 3?: EventDispatcherInterface, + * 4?: AsyncHandlerInterface, + * 5?: DriverInterface + * }|array{ + * "jobs"?: JobInterface|Closure|array, + * "errorJobs"?: JobInterface|Closure|array, + * "ipStrategy"?: IpStrategyInterface, + * "dispatcher"?: EventDispatcherInterface, + * "asyncHandler"?: AsyncHandlerInterface, + * "driver"?: DriverInterface + * } $config + * + * @return FlowInterface + */ + public function create(callable $callable, ?array $config = null): FlowInterface + { + /** + * @var Closure|Generator $generator + */ + $generator = $callable(); + + if ($generator instanceof Generator) { + return $this->createFromGenerator($generator, $config); + } + + return $this->createFlow($generator, $config); + } + + /** + * @param array|Closure|FlowInterface $flow + * @param ?array $config + * + * @return Flow + * + * #param ?array{ + * 0: Closure, + * 1?: Closure, + * 2?: IpStrategyInterface, + * 3?: EventDispatcherInterface, + * 4?: AsyncHandlerInterface, + * 5?: DriverInterface + * }|array{ + * "ipStrategy"?: IpStrategyInterface, + * "dispatcher"?: EventDispatcherInterface, + * "asyncHandler"?: AsyncHandlerInterface, + * "driver"?: DriverInterface + * } $config + */ + public function createFlow($flow, ?array $config = null): Flow + { + if ($flow instanceof Closure || $flow instanceof JobInterface) { + return new Flow(...[...['job' => $flow, 'driver' => $this->driver], ...($config ?? [])]); + } + if (is_array($flow)) { + if (array_key_exists(0, $flow) || array_key_exists('job', $flow)) { + return new Flow(...[...$flow, ...['driver' => $this->driver], ...($config ?? [])]); + } + + return $this->createFlowMap($flow); + } + + return $flow; + } + + /** + * @param ?array $config + * + * @return FlowInterface + */ + private function createFromGenerator(Generator $generator, ?array $config = null): FlowInterface + { + $flows = []; + + while ($generator->valid()) { + $flow = $this->createFlow($generator->current(), $config); + $generator->send($flow); + $flows[] = $flow; + } + + $return = $generator->getReturn(); + if (!empty($return)) { + $flows[] = $this->createFlow($return, $config); + } + + return $this->createFlowMap($flows); + } + + /** + * @param array> $flows + * + * @return Flow + */ + private function createFlowMap(array $flows): Flow + { + $flow = array_shift($flows); + if (null === $flow) { + throw new LogicException('Flow is empty'); + } + + foreach ($flows as $flowIt) { + $flow = $flow->fn($flowIt); + } + + return $flow; + } +} diff --git a/src/FlowInterface.php b/src/FlowInterface.php index 6f27a20c..f718994b 100644 --- a/src/FlowInterface.php +++ b/src/FlowInterface.php @@ -5,7 +5,6 @@ namespace Flow; use Closure; -use Generator; /** * @template T1 @@ -37,49 +36,6 @@ public function __invoke(Ip $ip): void; */ public function fn(array|Closure|JobInterface|self $flow): self; - /** - * Do-notation a.k.a. for-comprehension. - * - * Syntax sugar for sequential {@see FlowInterface::fn()} calls - * - * Syntax "$flow = yield $wrapedFlow" mean: - * 1) $wrapedFlow can be Closure as Job, array constructor arguments for Flow instanciation, array configuration for Flow instanciation or FlowInterface instance - * 2) $flow is assigned as FlowInterface instance - * 3) optionnaly you can return another wrapedFlow - * - * ```php - * $flow = Flow::do(static function() { - * yield new Flow(fn($a) => $a + 1); - * $flow = yield fn($b) => $b * 2; - * $flow = yield $flow->fn([fn($c) => $c * 4]) - * return [$flow, [fn($d) => $d - 8]]; - * }); - * ``` - * $config if provided will be the fallback array configuration for Flow instanciation - * - * @param callable(): Generator|Closure $callable - * @param ?array $config - * - * #param ?array{ - * 0: Closure|array, - * 1?: Closure|array, - * 2?: IpStrategyInterface, - * 3?: EventDispatcherInterface, - * 4?: AsyncHandlerInterface, - * 5?: DriverInterface - * }|array{ - * "jobs"?: JobInterface|Closure|array, - * "errorJobs"?: JobInterface|Closure|array, - * "ipStrategy"?: IpStrategyInterface, - * "dispatcher"?: EventDispatcherInterface, - * "asyncHandler"?: AsyncHandlerInterface, - * "driver"?: DriverInterface - * } $config - * - * @return FlowInterface - */ - public static function do(callable $callable, ?array $config = null): self; - /** * Await asynchonous call for current IPs. * After await, all IPs have been proceed, it continues synchronously. diff --git a/tests/Flow/FlowTest.php b/tests/Flow/FlowTest.php index e3c01491..c642c12a 100644 --- a/tests/Flow/FlowTest.php +++ b/tests/Flow/FlowTest.php @@ -14,6 +14,7 @@ use Flow\DriverInterface; use Flow\ExceptionInterface; use Flow\Flow\Flow; +use Flow\FlowFactory; use Flow\Ip; use Flow\IpStrategy\MaxIpStrategy; use Flow\Job\ClosureJob; @@ -124,7 +125,7 @@ static function (ExceptionInterface $exception) use ($cancel) { public function testDo(DriverInterface $driver, callable $callable, ?array $config, int $resultNumber): void { $ip = new Ip(new ArrayObject(['number' => 0])); - $flow = Flow::do($callable, [ + $flow = (new FlowFactory())->create($callable, [ ...['driver' => $driver], ...($config ?? []), ])->fn(static function (ArrayObject $data) use ($resultNumber) { From c3585b94b341fe622cc210d94db5c72f13113964 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Tue, 12 Nov 2024 18:07:44 +0100 Subject: [PATCH 13/14] :sparkles: Add ParallelDriver --- CHANGELOG.md | 1 + examples/flow.php | 2 + examples/yflow.php | 3 + src/Driver/ParallelDriver.php | 205 ++++++++++++++++++++++++++++++++++ tools/dev/Dockerfile | 7 +- tools/dev/docker-compose.yml | 1 - 6 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 src/Driver/ParallelDriver.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 378b8e1d..35ee188c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add `Flow\IpPool` for managing pools of Ips. - Update `Flow\Event\PullEvent` to pull multiple Ips instead one. - Move `Flow::do` to `FlowFactory::create` +- Add `Flow\Driver\ParallelDriver` ## v1.2.2 diff --git a/examples/flow.php b/examples/flow.php index d49ee947..6fae3db1 100644 --- a/examples/flow.php +++ b/examples/flow.php @@ -6,6 +6,7 @@ use Flow\Driver\AmpDriver; use Flow\Driver\FiberDriver; +use Flow\Driver\ParallelDriver; use Flow\Driver\ReactDriver; use Flow\Driver\SpatieDriver; use Flow\Driver\SwooleDriver; @@ -25,6 +26,7 @@ 3 => new ReactDriver(), 4 => new SwooleDriver(), // 5 => new SpatieDriver(), + // 6 => new ParallelDriver(), }; printf("Use %s\n", $driver::class); printf("Calculating:\n"); diff --git a/examples/yflow.php b/examples/yflow.php index ef53b703..47bb7859 100644 --- a/examples/yflow.php +++ b/examples/yflow.php @@ -7,6 +7,7 @@ use Flow\AsyncHandler\DeferAsyncHandler; use Flow\Driver\AmpDriver; use Flow\Driver\FiberDriver; +use Flow\Driver\ParallelDriver; use Flow\Driver\ReactDriver; use Flow\Driver\SpatieDriver; use Flow\Driver\SwooleDriver; @@ -23,7 +24,9 @@ 3 => new FiberDriver(), 4 => new SwooleDriver(), // 5 => new SpatieDriver(), + // 6 => new ParallelDriver(), }; + printf("Use %s\n", $driver::class); $factorial = static function (int $n) use (&$factorial): int { diff --git a/src/Driver/ParallelDriver.php b/src/Driver/ParallelDriver.php new file mode 100644 index 00000000..9174a256 --- /dev/null +++ b/src/Driver/ParallelDriver.php @@ -0,0 +1,205 @@ + + */ +class ParallelDriver implements DriverInterface +{ + use DriverTrait; + + /** + * @var array + */ + private array $ticks = []; + + public function __construct() + { + if (!class_exists(Runtime::class)) { + throw new NativeRuntimeException('Parallel extension is not loaded. Suggest install it with pecl install parallel'); + } + } + + public function async(Closure|JobInterface $callback): Closure + { + return static function (...$args) use ($callback) { + $runtime = new Runtime('vendor/autoload.php'); + + return $runtime->run(static function () use ($callback, $args) { + try { + return $callback(...$args); + } catch (Throwable $exception) { + return new RuntimeException($exception->getMessage(), $exception->getCode(), $exception); + } + }); + }; + } + + public function defer(Closure $callback): mixed + { + $runtime = new Runtime('vendor/autoload.php'); + + return $runtime->run(static function () use ($callback) { + try { + $result = null; + $callback( + static function ($value) use (&$result) { + $result = $value; + }, + static function ($fn, $next) { + $fn($next); + } + ); + + return $result; + } catch (Throwable $exception) { + return new RuntimeException($exception->getMessage(), $exception->getCode(), $exception); + } + }); + } + + public function await(array &$stream): void + { + $async = function ($isTick) use (&$parallelDatas) { + return function (Closure|JobInterface $job) use (&$parallelDatas, $isTick) { + return function (mixed $data) use (&$parallelDatas, $isTick, $job) { + $async = $this->async($job); + + $parallel = $async($data); + + $next = static function ($return) {}; + + $parallelDatas[] = [ + 'parallel' => $parallel, + 'next' => static function ($return) use (&$next) { + $next($return); + }, + ]; + + return static function (Closure $callback) use ($isTick, &$next) { + if ($isTick === false) { + $next = static function ($return) use ($callback) { + $callback($return); + }; + } + }; + }; + }; + }; + + $defer = static function ($isTick) use (&$parallelDatas) { + return static function (Closure|JobInterface $job) use ($isTick, &$parallelDatas) { + return static function (Closure $next) use ($isTick, $job, &$parallelDatas) { + $parallel = new Runtime('vendor/autoload.php'); + $parallel->run(static function () use ($isTick, $job, $next) { + try { + $job(static function ($return) use ($isTick, $next) { + if ($isTick === false) { + $next($return); + } + }, static function ($fn, $next) { + $fn($next); + }); + } catch (Throwable $exception) { + return new RuntimeException($exception->getMessage(), $exception->getCode(), $exception); + } + }); + + $parallelDatas[] = [ + 'parallel' => $parallel, + 'next' => static function ($return) {}, /*function ($return) use ($isTick, $next) { + if ($isTick === false) { + $next($return); + } + },*/ + ]; + }; + }; + }; + + $tick = 0; + $parallelDatas = []; + do { + foreach ($this->ticks as [ + 'interval' => $interval, + 'callback' => $callback, + ]) { + if ($tick % $interval === 0) { + $ip = new Ip(); + $async(true)($callback)($ip->data); + } + } + + foreach ($stream['dispatchers'] as $index => $dispatcher) { + $nextIps = $dispatcher->dispatch(new PullEvent(), Event::PULL)->getIps(); + foreach ($nextIps as $nextIp) { + $stream['dispatchers'][$index]->dispatch(new AsyncEvent(static function (Closure|JobInterface $job) use ($async) { + return $async(false)($job); + }, static function (Closure|JobInterface $job) use ($defer) { + return $defer(false)($job); + }, $stream['fnFlows'][$index]['job'], $nextIp, static function ($data) use (&$stream, $index, $nextIp) { + if ($data instanceof RuntimeException && array_key_exists($index, $stream['fnFlows']) && $stream['fnFlows'][$index]['errorJob'] !== null) { + $stream['fnFlows'][$index]['errorJob']($data); + } elseif (array_key_exists($index + 1, $stream['fnFlows'])) { + $ip = new Ip($data); + $stream['dispatchers'][$index + 1]->dispatch(new PushEvent($ip), Event::PUSH); + } + + $stream['dispatchers'][$index]->dispatch(new PopEvent($nextIp), Event::POP); + }), Event::ASYNC); + } + } + + foreach ($parallelDatas as $i => $parallelData) { // @phpstan-ignore-line see https://github.com/phpstan/phpstan/issues/11468 + if ($parallelData['parallel']->done()) { + $data = $parallelData['parallel']->value(); + $parallelData['next']($data); + unset($parallelDatas[$i]); + } + } + + $tick++; + } while ($this->countIps($stream['dispatchers']) > 0 or count($this->ticks) > 0); + } + + public function delay(float $seconds): void + { + sleep((int) $seconds); + } + + public function tick($interval, Closure $callback): Closure + { + $i = count($this->ticks) - 1; + $this->ticks[$i] = [ + 'interval' => $interval, + 'callback' => $callback, + ]; + + return function () use ($i) { + unset($this->ticks[$i]); + }; + } +} diff --git a/tools/dev/Dockerfile b/tools/dev/Dockerfile index 3421511d..3a588d55 100644 --- a/tools/dev/Dockerfile +++ b/tools/dev/Dockerfile @@ -1,6 +1,7 @@ # syntax=docker/dockerfile:1.6.0 -FROM php:8.3-fpm-alpine as php +#FROM php:8.3-fpm-alpine as php +FROM php:8.3-zts-alpine as php RUN apk add --update make curl @@ -18,8 +19,10 @@ RUN set -eux; \ pcntl \ pcov \ zip \ + parallel \ ; WORKDIR /flow -CMD ["php-fpm"] +#CMD ["php-fpm"] +CMD ["tail", "-f", "/dev/null"] diff --git a/tools/dev/docker-compose.yml b/tools/dev/docker-compose.yml index 3aad6efd..66bbeada 100644 --- a/tools/dev/docker-compose.yml +++ b/tools/dev/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3' services: php: image: flow-php From 3c8db3b8f3b56a0252b56d84d43a7e1e560b37ae Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Fri, 20 Dec 2024 16:10:27 +0100 Subject: [PATCH 14/14] :memo: Release Flow v1.2.3 --- CHANGELOG.md | 2 +- docs/package.json | 2 +- docs/src/content/en/docs/getting-started/driver.md | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35ee188c..55f53b25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v1.2.x +## v1.2.3 - Add event Event::POOL occurs when Flow needs to count IPs to process. - Add `Flow\IpPool` for managing pools of Ips. diff --git a/docs/package.json b/docs/package.json index 45dda545..786d9e55 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,7 +12,7 @@ "keywords": [ "flow" ], - "version": "1.2.2", + "version": "1.2.3", "browserslist": [ "defaults" ], diff --git a/docs/src/content/en/docs/getting-started/driver.md b/docs/src/content/en/docs/getting-started/driver.md index c58e1641..35bcac76 100644 --- a/docs/src/content/en/docs/getting-started/driver.md +++ b/docs/src/content/en/docs/getting-started/driver.md @@ -72,6 +72,16 @@ pecl install openswoole-22.0.0 More documentation can be found [https://openswoole.com](https://openswoole.com) +## Parallel Driver + +To use Parallel Driver, you have to require the library with PECL + +```bash +pecl install parallel +``` + +More documentation can be found [https://www.php.net/manual/en/book.parallel.php](https://www.php.net/manual/en/book.parallel.php) + ## Make your custom driver You can make your custom driver by implementing `Flow\DriverInterface`