From 6379c88ed96d8cd4ab604394e61cf579c3f1ee5a Mon Sep 17 00:00:00 2001 From: shellphy Date: Tue, 25 Jun 2024 09:42:06 +0800 Subject: [PATCH 1/9] Associate a static seq variable with a link handle instead of an RPC static variable --- src/RPC/RPC.php | 17 ++++++----------- src/Relay.php | 13 +++++++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/RPC/RPC.php b/src/RPC/RPC.php index 1e07e9f..f2d4b49 100644 --- a/src/RPC/RPC.php +++ b/src/RPC/RPC.php @@ -30,11 +30,6 @@ class RPC implements RPCInterface */ private ?string $service = null; - /** - * @var positive-int - */ - private static int $seq = 1; - /** * @param RelayInterface $relay * @param CodecInterface|null $codec @@ -76,7 +71,9 @@ public function withCodec(CodecInterface $codec): RPCInterface */ public function call(string $method, $payload, $options = null) { - $this->relay->send($this->packFrame($method, $payload)); + $seq = $this->relay->getNextSeq(); + + $this->relay->send($this->packFrame($method, $payload, $seq)); // wait for the frame confirmation $frame = $this->relay->waitFrame(); @@ -85,12 +82,10 @@ public function call(string $method, $payload, $options = null) throw new RPCException('Invalid RPC frame, options missing'); } - if ($frame->options[0] !== self::$seq) { + if ($frame->options[0] !== $seq) { throw new RPCException('Invalid RPC frame, sequence mismatch'); } - self::$seq++; - return $this->decodeResponse($frame, $options); } @@ -163,13 +158,13 @@ private function decodeResponse(Frame $frame, $options = null) * @param mixed $payload * @return Frame */ - private function packFrame(string $method, $payload): Frame + private function packFrame(string $method, $payload, int $seq): Frame { if ($this->service !== null) { $method = $this->service . '.' . \ucfirst($method); } $body = $method . $this->codec->encode($payload); - return new Frame($body, [self::$seq, \strlen($method)], $this->codec->getIndex()); + return new Frame($body, [$seq, \strlen($method)], $this->codec->getIndex()); } } diff --git a/src/Relay.php b/src/Relay.php index ec4794d..a967452 100644 --- a/src/Relay.php +++ b/src/Relay.php @@ -13,6 +13,11 @@ abstract class Relay implements RelayInterface public const PIPES = 'pipes'; protected const CONNECTION_EXP = '/(?P[^:\/]+):\/\/(?P[^:]+)(:(?P[^:]+))?/'; + /** + * @var int + */ + private int $seq = 1; + /** * Create relay using string address. * @@ -93,4 +98,12 @@ private static function openOut(string $output) return $resource; } + + /** + * @return int + */ + public function getNextSeq(): int + { + return $this->seq++; + } } From 26235401581e0dba6d56a513f92ad56ff0b81050 Mon Sep 17 00:00:00 2001 From: shellphy Date: Tue, 25 Jun 2024 19:13:03 +0800 Subject: [PATCH 2/9] add swoole test --- composer.json | 1 + src/RelayInterface.php | 5 ++++ tests/Goridge/SwooleTest.php | 50 ++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/Goridge/SwooleTest.php diff --git a/composer.json b/composer.json index e56ad8b..f5a98ec 100644 --- a/composer.json +++ b/composer.json @@ -36,6 +36,7 @@ "suggest": { "ext-msgpack": "MessagePack codec support", "ext-protobuf": "Protobuf codec support", + "ext-swoole": "Swoole gocoroutine support", "rybakit/msgpack": "(^0.7) MessagePack codec support", "google/protobuf": "(^3.0) Protobuf codec support" }, diff --git a/src/RelayInterface.php b/src/RelayInterface.php index 209983c..27e7f96 100644 --- a/src/RelayInterface.php +++ b/src/RelayInterface.php @@ -21,4 +21,9 @@ public function waitFrame(): Frame; * @param Frame $frame */ public function send(Frame $frame): void; + + /** + * @return int + */ + public function getNextSeq(): int; } diff --git a/tests/Goridge/SwooleTest.php b/tests/Goridge/SwooleTest.php new file mode 100644 index 0000000..b9d9b32 --- /dev/null +++ b/tests/Goridge/SwooleTest.php @@ -0,0 +1,50 @@ + SWOOLE_HOOK_ALL]); + Co\run(function () { + $methods = [ + 'testManualConnect', + 'testReconnect', + 'testPingPong', + 'testPrefixPingPong', + 'testPingNull', + 'testNegate', + 'testNegateNegative', + 'testLongEcho', + 'testRawBody', + 'testPayload', + 'testPayloadWithMap', + + // 'testBrokenPayloadMap', + // 'testJsonException' + // 'testInvalidService', + // 'testInvalidMethod', + // 'testConvertException', + // 'testBadPayload', + + // 'testLongRawBody', + ]; + + foreach ($methods as $method) { + $barrier = Barrier::make(); + for ($i = 0; $i < 2; $i++) { + go(function () use ($barrier, $method) { + $this->$method(); + }); + } + Barrier::wait($barrier); + } + }); + } +} \ No newline at end of file From dc99481b79cf7a4d2bcc1e5ab8c71eddc5691f2c Mon Sep 17 00:00:00 2001 From: shellphy Date: Tue, 25 Jun 2024 19:14:11 +0800 Subject: [PATCH 3/9] add swoole test --- tests/Goridge/SwooleTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Goridge/SwooleTest.php b/tests/Goridge/SwooleTest.php index b9d9b32..ee13658 100644 --- a/tests/Goridge/SwooleTest.php +++ b/tests/Goridge/SwooleTest.php @@ -38,7 +38,7 @@ public function testNoExceptionWithSwooleCoroutine(): void foreach ($methods as $method) { $barrier = Barrier::make(); - for ($i = 0; $i < 2; $i++) { + for ($i = 0; $i < 5; $i++) { go(function () use ($barrier, $method) { $this->$method(); }); From c17fc7a799534b2f57a1fe17b851d1d09a4c9307 Mon Sep 17 00:00:00 2001 From: shellphy Date: Tue, 25 Jun 2024 23:30:24 +0800 Subject: [PATCH 4/9] add swoole extension in ci --- .github/workflows/ci-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index f86f143..54d66d7 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -17,7 +17,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, xdebug + extensions: dom, xdebug, swoole - name: Check out code uses: actions/checkout@v2 From 47786b74012bee72d4eeccab23d540032206a9cc Mon Sep 17 00:00:00 2001 From: shellphy Date: Wed, 26 Jun 2024 00:00:38 +0800 Subject: [PATCH 5/9] test swoole alone in ci --- .github/workflows/ci-build.yml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 54d66d7..d0b7db2 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -12,12 +12,32 @@ jobs: matrix: php: ['7.4', '8.0', '8.1'] flag: ['--prefer-lowest', '--prefer-stable'] + include: + - php: '7.4' + extensions: 'dom, xdebug' + test-script: 'composer test-cover -- --exclude-group RPCTest' + - php: '7.4' + extensions: 'dom, swoole' + test-script: 'vendor/bin/phpunit --filter RPCTest' + - php: '8.0' + extensions: 'dom, xdebug' + test-script: 'composer test-cover -- --exclude-group RPCTest' + - php: '8.0' + extensions: 'dom, swoole' + test-script: 'vendor/bin/phpunit --filter RPCTest' + - php: '8.1' + extensions: 'dom, xdebug' + test-script: 'composer test-cover -- --exclude-group RPCTest' + - php: '8.1' + extensions: 'dom, swoole' + test-script: 'vendor/bin/phpunit --filter RPCTest' + steps: - name: Set up PHP ${{ matrix.php }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, xdebug, swoole + extensions: ${{ matrix.extensions }} - name: Check out code uses: actions/checkout@v2 @@ -46,7 +66,7 @@ jobs: run: docker run --name test-server --rm -d -p "7079:7079/tcp" test-server:local - name: Run tests - run: composer test-cover + run: ${{ matrix.test-script }} - uses: codecov/codecov-action@v1 # Docs: with: From 4b73a5a0269e269cbad5b48f3ff24f31f438dfec Mon Sep 17 00:00:00 2001 From: shellphy Date: Wed, 26 Jun 2024 09:38:22 +0800 Subject: [PATCH 6/9] remove swoole dependency --- .github/workflows/ci-build.yml | 26 ++---------------- composer.json | 1 - examples/swoole.php | 23 ++++++++++++++++ tests/Goridge/SwooleTest.php | 50 ---------------------------------- 4 files changed, 26 insertions(+), 74 deletions(-) create mode 100644 examples/swoole.php delete mode 100644 tests/Goridge/SwooleTest.php diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index d0b7db2..b83a956 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -12,32 +12,12 @@ jobs: matrix: php: ['7.4', '8.0', '8.1'] flag: ['--prefer-lowest', '--prefer-stable'] - include: - - php: '7.4' - extensions: 'dom, xdebug' - test-script: 'composer test-cover -- --exclude-group RPCTest' - - php: '7.4' - extensions: 'dom, swoole' - test-script: 'vendor/bin/phpunit --filter RPCTest' - - php: '8.0' - extensions: 'dom, xdebug' - test-script: 'composer test-cover -- --exclude-group RPCTest' - - php: '8.0' - extensions: 'dom, swoole' - test-script: 'vendor/bin/phpunit --filter RPCTest' - - php: '8.1' - extensions: 'dom, xdebug' - test-script: 'composer test-cover -- --exclude-group RPCTest' - - php: '8.1' - extensions: 'dom, swoole' - test-script: 'vendor/bin/phpunit --filter RPCTest' - steps: - name: Set up PHP ${{ matrix.php }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: ${{ matrix.extensions }} + extensions: dom, xdebug, swoole - name: Check out code uses: actions/checkout@v2 @@ -66,11 +46,11 @@ jobs: run: docker run --name test-server --rm -d -p "7079:7079/tcp" test-server:local - name: Run tests - run: ${{ matrix.test-script }} + run: composer test-cover - uses: codecov/codecov-action@v1 # Docs: with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage.xml flags: php - fail_ci_if_error: false + fail_ci_if_error: false \ No newline at end of file diff --git a/composer.json b/composer.json index f5a98ec..e56ad8b 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,6 @@ "suggest": { "ext-msgpack": "MessagePack codec support", "ext-protobuf": "Protobuf codec support", - "ext-swoole": "Swoole gocoroutine support", "rybakit/msgpack": "(^0.7) MessagePack codec support", "google/protobuf": "(^3.0) Protobuf codec support" }, diff --git a/examples/swoole.php b/examples/swoole.php new file mode 100644 index 0000000..c8b479c --- /dev/null +++ b/examples/swoole.php @@ -0,0 +1,23 @@ + SWOOLE_HOOK_ALL]); +Co\Run(function () { + $barrier = Barrier::make(); + for ($i = 0; $i < 3; $i++) { + go(function () use ($barrier) { + $rpc = new Goridge\RPC\RPC( + Goridge\Relay::create('tcp://127.0.0.1:6001') + ); + echo $rpc->call('App.Hi', 'Antony'); + }); + } + Barrier::wait($barrier); +}); \ No newline at end of file diff --git a/tests/Goridge/SwooleTest.php b/tests/Goridge/SwooleTest.php deleted file mode 100644 index ee13658..0000000 --- a/tests/Goridge/SwooleTest.php +++ /dev/null @@ -1,50 +0,0 @@ - SWOOLE_HOOK_ALL]); - Co\run(function () { - $methods = [ - 'testManualConnect', - 'testReconnect', - 'testPingPong', - 'testPrefixPingPong', - 'testPingNull', - 'testNegate', - 'testNegateNegative', - 'testLongEcho', - 'testRawBody', - 'testPayload', - 'testPayloadWithMap', - - // 'testBrokenPayloadMap', - // 'testJsonException' - // 'testInvalidService', - // 'testInvalidMethod', - // 'testConvertException', - // 'testBadPayload', - - // 'testLongRawBody', - ]; - - foreach ($methods as $method) { - $barrier = Barrier::make(); - for ($i = 0; $i < 5; $i++) { - go(function () use ($barrier, $method) { - $this->$method(); - }); - } - Barrier::wait($barrier); - } - }); - } -} \ No newline at end of file From 705ddc7cd2ae7e676dd56678ea57e8e83b78dfe4 Mon Sep 17 00:00:00 2001 From: shellphy Date: Wed, 26 Jun 2024 09:39:17 +0800 Subject: [PATCH 7/9] remove swoole dependency --- .github/workflows/ci-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index b83a956..c6652e2 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -17,7 +17,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, xdebug, swoole + extensions: dom, xdebug - name: Check out code uses: actions/checkout@v2 From 314c9cb768e37312eae69d809daa1bbdf104000f Mon Sep 17 00:00:00 2001 From: shellphy Date: Thu, 27 Jun 2024 10:17:36 +0800 Subject: [PATCH 8/9] change seq to no-static variable --- src/RPC/RPC.php | 17 +++++++++++------ src/Relay.php | 13 ------------- src/RelayInterface.php | 5 ----- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/RPC/RPC.php b/src/RPC/RPC.php index f2d4b49..adce49a 100644 --- a/src/RPC/RPC.php +++ b/src/RPC/RPC.php @@ -30,6 +30,11 @@ class RPC implements RPCInterface */ private ?string $service = null; + /** + * @var positive-int + */ + private int $seq = 1; + /** * @param RelayInterface $relay * @param CodecInterface|null $codec @@ -71,9 +76,7 @@ public function withCodec(CodecInterface $codec): RPCInterface */ public function call(string $method, $payload, $options = null) { - $seq = $this->relay->getNextSeq(); - - $this->relay->send($this->packFrame($method, $payload, $seq)); + $this->relay->send($this->packFrame($method, $payload)); // wait for the frame confirmation $frame = $this->relay->waitFrame(); @@ -82,10 +85,12 @@ public function call(string $method, $payload, $options = null) throw new RPCException('Invalid RPC frame, options missing'); } - if ($frame->options[0] !== $seq) { + if ($frame->options[0] !== $this->seq) { throw new RPCException('Invalid RPC frame, sequence mismatch'); } + $this->seq++; + return $this->decodeResponse($frame, $options); } @@ -158,13 +163,13 @@ private function decodeResponse(Frame $frame, $options = null) * @param mixed $payload * @return Frame */ - private function packFrame(string $method, $payload, int $seq): Frame + private function packFrame(string $method, $payload): Frame { if ($this->service !== null) { $method = $this->service . '.' . \ucfirst($method); } $body = $method . $this->codec->encode($payload); - return new Frame($body, [$seq, \strlen($method)], $this->codec->getIndex()); + return new Frame($body, [$this->seq, \strlen($method)], $this->codec->getIndex()); } } diff --git a/src/Relay.php b/src/Relay.php index a967452..ec4794d 100644 --- a/src/Relay.php +++ b/src/Relay.php @@ -13,11 +13,6 @@ abstract class Relay implements RelayInterface public const PIPES = 'pipes'; protected const CONNECTION_EXP = '/(?P[^:\/]+):\/\/(?P[^:]+)(:(?P[^:]+))?/'; - /** - * @var int - */ - private int $seq = 1; - /** * Create relay using string address. * @@ -98,12 +93,4 @@ private static function openOut(string $output) return $resource; } - - /** - * @return int - */ - public function getNextSeq(): int - { - return $this->seq++; - } } diff --git a/src/RelayInterface.php b/src/RelayInterface.php index 27e7f96..209983c 100644 --- a/src/RelayInterface.php +++ b/src/RelayInterface.php @@ -21,9 +21,4 @@ public function waitFrame(): Frame; * @param Frame $frame */ public function send(Frame $frame): void; - - /** - * @return int - */ - public function getNextSeq(): int; } From baadfc8ff58f26f1c59a48385d122dc025291d62 Mon Sep 17 00:00:00 2001 From: shellphy Date: Thu, 27 Jun 2024 10:51:22 +0800 Subject: [PATCH 9/9] change seq to no-static variable --- src/RPC/RPC.php | 9 --------- src/Relay.php | 2 -- src/RelayInterface.php | 5 ++++- tests/Goridge/RPCTest.php | 2 +- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/RPC/RPC.php b/src/RPC/RPC.php index 446ae26..adce49a 100644 --- a/src/RPC/RPC.php +++ b/src/RPC/RPC.php @@ -32,15 +32,9 @@ class RPC implements RPCInterface /** * @var positive-int - * @deprecated since v3.2.1. */ private int $seq = 1; - /** - * @deprecated since v3.2.1. Need for backward compatibility. - */ - private bool $hasSequence = false; - /** * @param RelayInterface $relay * @param CodecInterface|null $codec @@ -49,8 +43,6 @@ public function __construct(RelayInterface $relay, CodecInterface $codec = null) { $this->relay = $relay; $this->codec = $codec ?? new JsonCodec(); - /** @psalm-suppress DeprecatedProperty */ - $this->hasSequence = \method_exists($this->relay, 'getNextSequence'); } /** @@ -178,7 +170,6 @@ private function packFrame(string $method, $payload): Frame } $body = $method . $this->codec->encode($payload); - return new Frame($body, [$this->seq, \strlen($method)], $this->codec->getIndex()); } } diff --git a/src/Relay.php b/src/Relay.php index 3caefa7..ec4794d 100644 --- a/src/Relay.php +++ b/src/Relay.php @@ -13,8 +13,6 @@ abstract class Relay implements RelayInterface public const PIPES = 'pipes'; protected const CONNECTION_EXP = '/(?P[^:\/]+):\/\/(?P[^:]+)(:(?P[^:]+))?/'; - private int $sequence = 1; - /** * Create relay using string address. * diff --git a/src/RelayInterface.php b/src/RelayInterface.php index c425999..209983c 100644 --- a/src/RelayInterface.php +++ b/src/RelayInterface.php @@ -8,14 +8,17 @@ /** * Blocking, duplex relay. - * @method getNextSequence(): int */ interface RelayInterface { /** + * @return Frame * @throws RelayException */ public function waitFrame(): Frame; + /** + * @param Frame $frame + */ public function send(Frame $frame): void; } diff --git a/tests/Goridge/RPCTest.php b/tests/Goridge/RPCTest.php index f817837..165a397 100644 --- a/tests/Goridge/RPCTest.php +++ b/tests/Goridge/RPCTest.php @@ -157,7 +157,7 @@ public function testLongRawBody(): void { $conn = $this->makeRPC(); $payload = random_bytes(65000 * 1000); - + $resp = $conn->withCodec(new RawCodec())->call( 'Service.EchoBinary', $payload