diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..d5071af
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+/.github export-ignore
+/.vscode export-ignore
+/tests export-ignore
+.gitattributes export-ignore
+/bin export-ignore
\ No newline at end of file
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..84136de
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,28 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - "v*.*.*"
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Get the version
+ id: get_version
+ if: startsWith(github.ref, 'refs/tags/')
+ run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
+
+ - name: Release
+ uses: softprops/action-gh-release@v2
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ tag_name: ${{ github.ref }}
+ name: Release ${{ steps.get_version.outputs.VERSION }}
+ draft: false
+ prerelease: false
+ generate_release_notes: true
\ No newline at end of file
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 2a984dc..05aa6e2 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -10,7 +10,8 @@ jobs:
matrix:
os: [ubuntu-latest]
php-version: ['7.1', '7.2', '7.3', '7.4', '8.0']
- max-parallel: 3
+ max-parallel: 20
+ fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -25,10 +26,11 @@ jobs:
- name: Run Analyse
run: |
composer analyse src
+ - name: Setup Consul
+ run: docker run -d --name=dev-consul -e CONSUL_BIND_INTERFACE=eth0 --net=host consul:1.15.4
- name: Setup Services
run: |
- docker run -d --name jsonrpc -p 9501:9501 -p 9502:9502 -p 9503:9503 -p 9504:9504 limingxinleo/hyperf-jsonrpc-demo:latest
- docker run -d --name dev-consul -e CONSUL_BIND_INTERFACE=eth0 --network host consul
+ docker run -d --name jsonrpc -p 9501:9501 -p 9502:9502 -p 9503:9503 -p 9504:9504 -p 9505:9505 iisiam/hyperf-rpc-demo:latest
sleep 10
php ./tests/register.php
- name: Run Test Cases
diff --git a/.gitignore b/.gitignore
index 5aaa618..d52b9bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@ composer.lock
*.bak
/phpunit.xml
/.phpunit.result.cache
+.idea
+.bashrc
\ No newline at end of file
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
index c087f33..fb874a4 100644
--- a/.php-cs-fixer.php
+++ b/.php-cs-fixer.php
@@ -1,12 +1,11 @@
setTransporter(new GuzzleHttpTransporter('127.0.0.1', 9502));
-$metadata->setRegistry(new ConsulRegistry(['uri' => 'http://127.0.0.1:8500']));
+$metadata = (new Metadata('CalculatorService'))
+ ->withTransporter(new GuzzleHttpTransporter('127.0.0.1', 9502))
+ ->withRegistry(new ConsulRegistry(['uri' => 'http://127.0.0.1:8500']));
ServiceManager::register('CalculatorService', $metadata);
-~~~
+```
### Register default registry
-~~~php
+```php
use FriendsOfHyperf\Jet\RegistryManager;
use FriendsOfHyperf\Jet\Registry\ConsulRegistry;
RegistryManager::register(RegistryManager::DEFAULT, new ConsulRegistry(['uri' => $uri, 'timeout' => 1]));
-~~~
+```
> In Laravel project, Add to `boot()` in `App/Providers/AppServiceProvider.php`
@@ -47,16 +47,16 @@ RegistryManager::register(RegistryManager::DEFAULT, new ConsulRegistry(['uri' =>
### Call by ClientFactory
-~~~php
+```php
use FriendsOfHyperf\Jet\ClientFactory;
$client = ClientFactory::create('CalculatorService');
var_dump($client->add(1, 20));
-~~~
+```
### Call by custom client
-~~~php
+```php
use FriendsOfHyperf\Jet\Client;
use FriendsOfHyperf\Jet\Transporter\GuzzleHttpTransporter;
use FriendsOfHyperf\Jet\Registry\ConsulRegistry;
@@ -68,13 +68,9 @@ class CalculatorService extends Client
{
public function __construct($service = 'CalculatorService')
{
- $metadata = new Metadata($service);
-
- // Custom transporter
- $metadata->setTransporter(new GuzzleHttpTransporter('127.0.0.1', 9502));
-
- // Custom registry
- $metadata->setRegistry(new ConsulRegistry(['uri' => 'http://127.0.0.1:8500']));
+ $metadata = (new Metadata($service))
+ ->withTransporter(new GuzzleHttpTransporter('127.0.0.1', 9502))
+ ->withRegistry(new ConsulRegistry(['uri' => 'http://127.0.0.1:8500']));
parent::__construct($metadata);
}
@@ -82,11 +78,11 @@ class CalculatorService extends Client
$service = new CalculatorService;
var_dump($service->add(3, 10));
-~~~
+```
### Call by custom facade
-~~~php
+```php
use FriendsOfHyperf\Jet\Facade;
use FriendsOfHyperf\Jet\ClientFactory;
@@ -103,22 +99,52 @@ class Calculator extends Facade
}
var_dump(Calculator::add(rand(0, 100), rand(0, 100)));
-~~~
+```
## Coroutine support in Hyperf
-~~~php
-// config/autoload/annotations.php
+- Aspect
+
+```php
+clientFactory = $clientFactory;
+ }
+
+ public function process(ProceedingJoinPoint $proceedingJoinPoint)
+ {
+ $instance = $proceedingJoinPoint->getInstance();
+ $config = (function () { return $this->config; })->call($instance);
+
+ return $this->clientFactory->create($config);
+ }
+}
+```
+
+- Config `config/autoload/aspects.php`
+
+```php
[
- // ...
- 'class_map' => [
- GuzzleHttp\Client::class => BASE_PATH . '/vendor/friendsofhyperf/jet/classmap/GuzzleHttp/Client.php',
- ],
- ],
+ 'App\Aspect\GuzzleHttpTransporterAspect',
];
-~~~
+```
diff --git a/bootstrap.php b/bootstrap.php
index dd9ce5e..7586ea0 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -2,12 +2,11 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
! defined('BASE_PATH') && define('BASE_PATH', __DIR__);
diff --git a/classmap/GuzzleHttp/Client.php b/classmap/GuzzleHttp/Client.php
deleted file mode 100644
index 79be25f..0000000
--- a/classmap/GuzzleHttp/Client.php
+++ /dev/null
@@ -1,489 +0,0 @@
- 'http://www.foo.com/1.0/',
- * 'timeout' => 0,
- * 'allow_redirects' => false,
- * 'proxy' => '192.168.16.1:10'
- * ]);
- *
- * Client configuration settings include the following options:
- *
- * - handler: (callable) Function that transfers HTTP requests over the
- * wire. The function is called with a Psr7\Http\Message\RequestInterface
- * and array of transfer options, and must return a
- * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
- * Psr7\Http\Message\ResponseInterface on success.
- * If no handler is provided, a default handler will be created
- * that enables all of the request options below by attaching all of the
- * default middleware to the handler.
- * - base_uri: (string|UriInterface) Base URI of the client that is merged
- * into relative URIs. Can be a string or instance of UriInterface.
- * - **: any request option
- *
- * @param array $config client configuration settings
- *
- * @see \GuzzleHttp\RequestOptions for a list of available request options.
- */
- public function __construct(array $config = [])
- {
- $inCoroutine = Coroutine::inCoroutine();
- if (! isset($config['handler'])) {
- // 对应的 Handler 可以按需选择 CoroutineHandler 或 PoolHandler
- $config['handler'] = HandlerStack::create($inCoroutine ? new CoroutineHandler() : null);
- } elseif ($inCoroutine && $config['handler'] instanceof HandlerStack) {
- $config['handler']->setHandler(new CoroutineHandler());
- } elseif (! is_callable($config['handler'])) {
- throw new \InvalidArgumentException('handler must be a callable');
- }
-
- // Convert the base_uri to a UriInterface
- if (isset($config['base_uri'])) {
- $config['base_uri'] = Psr7\uri_for($config['base_uri']);
- }
-
- $this->configureDefaults($config);
- }
-
- /**
- * @param string $method
- * @param array $args
- *
- * @return PromiseInterface|ResponseInterface
- *
- * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0.
- */
- public function __call($method, $args)
- {
- if (\count($args) < 1) {
- throw new InvalidArgumentException('Magic request methods require a URI and optional options array');
- }
-
- $uri = $args[0];
- $opts = $args[1] ?? [];
-
- return \substr($method, -5) === 'Async'
- ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts)
- : $this->request($method, $uri, $opts);
- }
-
- /**
- * Asynchronously send an HTTP request.
- *
- * @param array $options Request options to apply to the given
- * request and to the transfer. See \GuzzleHttp\RequestOptions.
- */
- public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface
- {
- // Merge the base URI into the request URI if needed.
- $options = $this->prepareDefaults($options);
-
- return $this->transfer(
- $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
- $options
- );
- }
-
- /**
- * Send an HTTP request.
- *
- * @param array $options Request options to apply to the given
- * request and to the transfer. See \GuzzleHttp\RequestOptions.
- *
- * @throws GuzzleException
- */
- public function send(RequestInterface $request, array $options = []): ResponseInterface
- {
- $options[RequestOptions::SYNCHRONOUS] = true;
- return $this->sendAsync($request, $options)->wait();
- }
-
- /**
- * The HttpClient PSR (PSR-18) specify this method.
- *
- * {@inheritDoc}
- */
- public function sendRequest(RequestInterface $request): ResponseInterface
- {
- $options[RequestOptions::SYNCHRONOUS] = true;
- $options[RequestOptions::ALLOW_REDIRECTS] = false;
- $options[RequestOptions::HTTP_ERRORS] = false;
-
- return $this->sendAsync($request, $options)->wait();
- }
-
- /**
- * Create and send an asynchronous HTTP request.
- *
- * Use an absolute path to override the base path of the client, or a
- * relative path to append to the base path of the client. The URL can
- * contain the query string as well. Use an array to provide a URL
- * template and additional variables to use in the URL template expansion.
- *
- * @param string $method HTTP method
- * @param string|UriInterface $uri URI object or string
- * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
- */
- public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface
- {
- $options = $this->prepareDefaults($options);
- // Remove request modifying parameter because it can be done up-front.
- $headers = $options['headers'] ?? [];
- $body = $options['body'] ?? null;
- $version = $options['version'] ?? '1.1';
- // Merge the URI into the base URI.
- $uri = $this->buildUri(Psr7\Utils::uriFor($uri), $options);
- if (\is_array($body)) {
- throw $this->invalidBody();
- }
- $request = new Psr7\Request($method, $uri, $headers, $body, $version);
- // Remove the option so that they are not doubly-applied.
- unset($options['headers'], $options['body'], $options['version']);
-
- return $this->transfer($request, $options);
- }
-
- /**
- * Create and send an HTTP request.
- *
- * Use an absolute path to override the base path of the client, or a
- * relative path to append to the base path of the client. The URL can
- * contain the query string as well.
- *
- * @param string $method HTTP method
- * @param string|UriInterface $uri URI object or string
- * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
- *
- * @throws GuzzleException
- */
- public function request(string $method, $uri = '', array $options = []): ResponseInterface
- {
- $options[RequestOptions::SYNCHRONOUS] = true;
- return $this->requestAsync($method, $uri, $options)->wait();
- }
-
- /**
- * Get a client configuration option.
- *
- * These options include default request options of the client, a "handler"
- * (if utilized by the concrete client), and a "base_uri" if utilized by
- * the concrete client.
- *
- * @param null|string $option the config option to retrieve
- *
- * @return mixed
- *
- * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.
- */
- public function getConfig(?string $option = null)
- {
- return $option === null
- ? $this->config
- : (isset($this->config[$option]) ? $this->config[$option] : null);
- }
-
- private function buildUri(UriInterface $uri, array $config): UriInterface
- {
- if (isset($config['base_uri'])) {
- $uri = Psr7\UriResolver::resolve(Psr7\Utils::uriFor($config['base_uri']), $uri);
- }
-
- if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
- $idnOptions = ($config['idn_conversion'] === true) ? \IDNA_DEFAULT : $config['idn_conversion'];
- $uri = Utils::idnUriConvert($uri, $idnOptions);
- }
-
- return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
- }
-
- /**
- * Configures the default options for a client.
- */
- private function configureDefaults(array $config): void
- {
- $defaults = [
- 'allow_redirects' => RedirectMiddleware::$defaultSettings,
- 'http_errors' => true,
- 'decode_content' => true,
- 'verify' => true,
- 'cookies' => false,
- 'idn_conversion' => false,
- ];
-
- // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
-
- // We can only trust the HTTP_PROXY environment variable in a CLI
- // process due to the fact that PHP has no reliable mechanism to
- // get environment variables that start with "HTTP_".
- if (\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) {
- $defaults['proxy']['http'] = $proxy;
- }
-
- if ($proxy = Utils::getenv('HTTPS_PROXY')) {
- $defaults['proxy']['https'] = $proxy;
- }
-
- if ($noProxy = Utils::getenv('NO_PROXY')) {
- $cleanedNoProxy = \str_replace(' ', '', $noProxy);
- $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy);
- }
-
- $this->config = $config + $defaults;
-
- if (! empty($config['cookies']) && $config['cookies'] === true) {
- $this->config['cookies'] = new CookieJar();
- }
-
- // Add the default user-agent header.
- if (! isset($this->config['headers'])) {
- $this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()];
- } else {
- // Add the User-Agent header if one was not already set.
- foreach (\array_keys($this->config['headers']) as $name) {
- if (\strtolower($name) === 'user-agent') {
- return;
- }
- }
- $this->config['headers']['User-Agent'] = Utils::defaultUserAgent();
- }
- }
-
- /**
- * Merges default options into the array.
- *
- * @param array $options Options to modify by reference
- */
- private function prepareDefaults(array $options): array
- {
- $defaults = $this->config;
-
- if (! empty($defaults['headers'])) {
- // Default headers are only added if they are not present.
- $defaults['_conditional'] = $defaults['headers'];
- unset($defaults['headers']);
- }
-
- // Special handling for headers is required as they are added as
- // conditional headers and as headers passed to a request ctor.
- if (\array_key_exists('headers', $options)) {
- // Allows default headers to be unset.
- if ($options['headers'] === null) {
- $defaults['_conditional'] = [];
- unset($options['headers']);
- } elseif (! \is_array($options['headers'])) {
- throw new InvalidArgumentException('headers must be an array');
- }
- }
-
- // Shallow merge defaults underneath options.
- $result = $options + $defaults;
-
- // Remove null values.
- foreach ($result as $k => $v) {
- if ($v === null) {
- unset($result[$k]);
- }
- }
-
- return $result;
- }
-
- /**
- * Transfers the given request and applies request options.
- *
- * The URI of the request is not modified and the request options are used
- * as-is without merging in default options.
- *
- * @param array $options see \GuzzleHttp\RequestOptions
- */
- private function transfer(RequestInterface $request, array $options): PromiseInterface
- {
- $request = $this->applyOptions($request, $options);
- /** @var HandlerStack $handler */
- $handler = $options['handler'];
-
- try {
- return P\Create::promiseFor($handler($request, $options));
- } catch (\Exception $e) {
- return P\Create::rejectionFor($e);
- }
- }
-
- /**
- * Applies the array of request options to a request.
- */
- private function applyOptions(RequestInterface $request, array &$options): RequestInterface
- {
- $modify = [
- 'set_headers' => [],
- ];
-
- if (isset($options['headers'])) {
- $modify['set_headers'] = $options['headers'];
- unset($options['headers']);
- }
-
- if (isset($options['form_params'])) {
- if (isset($options['multipart'])) {
- throw new InvalidArgumentException('You cannot use '
- . 'form_params and multipart at the same time. Use the '
- . 'form_params option if you want to send application/'
- . 'x-www-form-urlencoded requests, and the multipart '
- . 'option to send multipart/form-data requests.');
- }
- $options['body'] = \http_build_query($options['form_params'], '', '&');
- unset($options['form_params']);
- // Ensure that we don't have the header in different case and set the new value.
- $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
- $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
- }
-
- if (isset($options['multipart'])) {
- $options['body'] = new Psr7\MultipartStream($options['multipart']);
- unset($options['multipart']);
- }
-
- if (isset($options['json'])) {
- $options['body'] = Utils::jsonEncode($options['json']);
- unset($options['json']);
- // Ensure that we don't have the header in different case and set the new value.
- $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
- $options['_conditional']['Content-Type'] = 'application/json';
- }
-
- if (! empty($options['decode_content'])
- && $options['decode_content'] !== true
- ) {
- // Ensure that we don't have the header in different case and set the new value.
- $options['_conditional'] = Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']);
- $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
- }
-
- if (isset($options['body'])) {
- if (\is_array($options['body'])) {
- throw $this->invalidBody();
- }
- $modify['body'] = Psr7\Utils::streamFor($options['body']);
- unset($options['body']);
- }
-
- if (! empty($options['auth']) && \is_array($options['auth'])) {
- $value = $options['auth'];
- $type = isset($value[2]) ? \strtolower($value[2]) : 'basic';
- switch ($type) {
- case 'basic':
- // Ensure that we don't have the header in different case and set the new value.
- $modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']);
- $modify['set_headers']['Authorization'] = 'Basic '
- . \base64_encode("{$value[0]}:{$value[1]}");
- break;
- case 'digest':
- // @todo: Do not rely on curl
- $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST;
- $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}";
- break;
- case 'ntlm':
- $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM;
- $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}";
- break;
- }
- }
-
- if (isset($options['query'])) {
- $value = $options['query'];
- if (\is_array($value)) {
- $value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986);
- }
- if (! \is_string($value)) {
- throw new InvalidArgumentException('query must be a string or array');
- }
- $modify['query'] = $value;
- unset($options['query']);
- }
-
- // Ensure that sink is not an invalid value.
- if (isset($options['sink'])) {
- // TODO: Add more sink validation?
- if (\is_bool($options['sink'])) {
- throw new InvalidArgumentException('sink must not be a boolean');
- }
- }
-
- $request = Psr7\Utils::modifyRequest($request, $modify);
- if ($request->getBody() instanceof Psr7\MultipartStream) {
- // Use a multipart/form-data POST if a Content-Type is not set.
- // Ensure that we don't have the header in different case and set the new value.
- $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
- $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
- . $request->getBody()->getBoundary();
- }
-
- // Merge in conditional headers if they are not present.
- if (isset($options['_conditional'])) {
- // Build up the changes so it's in a single clone of the message.
- $modify = [];
- foreach ($options['_conditional'] as $k => $v) {
- if (! $request->hasHeader($k)) {
- $modify['set_headers'][$k] = $v;
- }
- }
- $request = Psr7\Utils::modifyRequest($request, $modify);
- // Don't pass this internal value along to middleware/handlers.
- unset($options['_conditional']);
- }
-
- return $request;
- }
-
- /**
- * Return an InvalidArgumentException with pre-set message.
- */
- private function invalidBody(): InvalidArgumentException
- {
- return new InvalidArgumentException('Passing in the "body" request '
- . 'option as an array to send a request is not supported. '
- . 'Please use the "form_params" request option to send a '
- . 'application/x-www-form-urlencoded request, or the "multipart" '
- . 'request option to send a multipart/form-data request.');
- }
-}
diff --git a/composer.json b/composer.json
index 9cb412b..7673da2 100644
--- a/composer.json
+++ b/composer.json
@@ -8,13 +8,13 @@
"email": "huangdijia@gmail.com"
}],
"require": {
- "php": ">=7.0",
+ "php": ">=7.1",
"guzzlehttp/guzzle": "^6.0|^7.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"mockery/mockery": "^1.0",
- "phpstan/phpstan": "^0.12",
+ "phpstan/phpstan": "^1.0",
"phpunit/phpunit": "^7.0|^8.0|^9.0|^10.0"
},
"autoload": {
@@ -22,7 +22,7 @@
"FriendsOfHyperf\\Jet\\": "src/"
},
"files": [
- "src/helpers.php"
+ "src/Functions.php"
]
},
"autoload-dev": {
@@ -31,7 +31,10 @@
}
},
"config": {
- "sort-packages": true
+ "sort-packages": true,
+ "allow-plugins": {
+ "ergebnis/composer-normalize": true
+ }
},
"suggest": {
"swoole": ">=4.6.0"
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 3b21407..5b4e2dd 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -27,5 +27,8 @@
+
+
+
diff --git a/src/Client.php b/src/Client.php
index 832c244..bedb535 100644
--- a/src/Client.php
+++ b/src/Client.php
@@ -2,18 +2,17 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet;
use FriendsOfHyperf\Jet\Exception\RecvFailedException;
use FriendsOfHyperf\Jet\Exception\ServerException;
-use Throwable;
class Client
{
@@ -35,8 +34,8 @@ public function __construct(Metadata $metadata)
/**
* @param string $name
* @param array $arguments
- * @throws Throwable
* @return mixed
+ * @throws \Throwable
*/
public function __call($name, $arguments)
{
@@ -64,12 +63,12 @@ public function __call($name, $arguments)
throw new RecvFailedException('Recv failed');
}
- return with($packer->unpack($ret), function ($data) {
+ return with((array) $packer->unpack($ret), function ($data) use ($ret) {
if (array_key_exists('result', $data)) {
return $data['result'];
}
- throw new ServerException($data['error'] ?? []);
+ throw new ServerException($data['error'] ?? ['code' => 0, 'message' => 'Invalid data: ' . $ret]);
});
};
diff --git a/src/ClientFactory.php b/src/ClientFactory.php
index fb43fca..8691c6c 100644
--- a/src/ClientFactory.php
+++ b/src/ClientFactory.php
@@ -2,91 +2,76 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet;
-use Exception;
use FriendsOfHyperf\Jet\Contract\DataFormatterInterface;
use FriendsOfHyperf\Jet\Contract\PackerInterface;
use FriendsOfHyperf\Jet\Contract\PathGeneratorInterface;
use FriendsOfHyperf\Jet\Contract\TransporterInterface;
-use GuzzleHttp\ClientInterface;
-use InvalidArgumentException;
class ClientFactory
{
- /**
- * User agent.
- * @var string
- */
- protected static $userAgent;
-
- /**
- * Set user agent.
- */
- public static function setUserAgent(string $userAgent): void
- {
- self::$userAgent = $userAgent;
- }
-
- /**
- * Get user agent.
- */
- public static function getUserAgent(): string
- {
- return self::$userAgent ?: sprintf(
- 'jet/%s php/%s guzzle/%s curl/%s',
- Client::MAJOR_VERSION,
- PHP_VERSION,
- defined(ClientInterface::class . '::VERSION') ? constant(ClientInterface::class . '::VERSION') : constant(ClientInterface::class . '::MAJOR_VERSION'),
- curl_version()['version']
- );
- }
-
/**
* Create a client.
* @param null|int|string|TransporterInterface $transporter transporter, protocol, timeout or null
- * @throws InvalidArgumentException
- * @throws Exception
+ * @throws \InvalidArgumentException
+ * @throws \Exception
*/
- public static function create(string $service, $transporter = null, ?PackerInterface $packer = null, ?DataFormatterInterface $dataFormatter = null, ?PathGeneratorInterface $pathGenerator = null, ?int $tries = null): Client
- {
- if (! $metadata = ServiceManager::get($service)) {
- $metadata = new Metadata($service);
+ public static function create(
+ string $service,
+ $transporter = null,
+ ?PackerInterface $packer = null,
+ ?DataFormatterInterface $dataFormatter = null,
+ ?PathGeneratorInterface $pathGenerator = null,
+ ?int $tries = null
+ ): Client {
+ if ($metadata = ServiceManager::get($service)) {
+ return new Client($metadata);
+ }
+
+ if (
+ func_num_args() == 2
+ && is_string($transporter)
+ && $metadata = MetadataManager::get($transporter)
+ ) {
+ return new Client($metadata->withName($service));
+ }
+
+ $metadata = new Metadata($service);
- if (RegistryManager::isRegistered(RegistryManager::DEFAULT)) {
- $metadata->setRegistry(RegistryManager::get(RegistryManager::DEFAULT));
- }
+ if (RegistryManager::isRegistered(RegistryManager::DEFAULT)) {
+ $metadata = $metadata->withRegistry(RegistryManager::get(RegistryManager::DEFAULT));
+ }
- if ($transporter instanceof TransporterInterface) {
- $metadata->setTransporter($transporter);
- } elseif (is_numeric($transporter)) {
- $metadata->setTimeout($transporter);
- } elseif (is_string($transporter)) {
- $metadata->setProtocol($transporter);
- }
+ if ($transporter instanceof TransporterInterface) {
+ $metadata = $metadata->withTransporter($transporter);
+ } elseif (is_numeric($transporter)) {
+ $metadata = $metadata->withTimeout($transporter);
+ } elseif (is_string($transporter)) {
+ $metadata = $metadata->withProtocol($transporter);
+ }
- if ($packer) {
- $metadata->setPacker($packer);
- }
+ if ($packer) {
+ $metadata = $metadata->withPacker($packer);
+ }
- if ($dataFormatter) {
- $metadata->setDataFormatter($dataFormatter);
- }
+ if ($dataFormatter) {
+ $metadata = $metadata->withDataFormatter($dataFormatter);
+ }
- if ($pathGenerator) {
- $metadata->setPathGenerator($pathGenerator);
- }
+ if ($pathGenerator) {
+ $metadata = $metadata->withPathGenerator($pathGenerator);
+ }
- if ($tries) {
- $metadata->setTries($tries);
- }
+ if ($tries) {
+ $metadata = $metadata->withTries($tries);
}
return new Client($metadata);
diff --git a/src/Consul/Agent.php b/src/Consul/Agent.php
index 88d4196..6bedc1f 100644
--- a/src/Consul/Agent.php
+++ b/src/Consul/Agent.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Consul;
class Agent extends Client
diff --git a/src/Consul/Catalog.php b/src/Consul/Catalog.php
index 4f73393..272d3f6 100644
--- a/src/Consul/Catalog.php
+++ b/src/Consul/Catalog.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Consul;
use FriendsOfHyperf\Jet\Exception\ClientException;
@@ -18,10 +18,10 @@
class Catalog extends Client
{
/**
+ * @return Response
* @throws ServerException
* @throws ClientException
* @throws GuzzleException
- * @return Response
*/
public function services(array $options = [])
{
diff --git a/src/Consul/Client.php b/src/Consul/Client.php
index 07cfc40..73e76a2 100644
--- a/src/Consul/Client.php
+++ b/src/Consul/Client.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Consul;
use FriendsOfHyperf\Jet\Exception\ClientException;
diff --git a/src/Consul/Health.php b/src/Consul/Health.php
index 44c649b..505c80e 100644
--- a/src/Consul/Health.php
+++ b/src/Consul/Health.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Consul;
class Health extends Client
diff --git a/src/Consul/Response.php b/src/Consul/Response.php
index 89b145a..6b05760 100644
--- a/src/Consul/Response.php
+++ b/src/Consul/Response.php
@@ -2,16 +2,17 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Consul;
use FriendsOfHyperf\Jet\Exception\ServerException;
+use FriendsOfHyperf\Jet\Support\Arr;
use Psr\Http\Message\ResponseInterface;
class Response
@@ -38,10 +39,10 @@ public function __call($name, $arguments)
/**
* @param null|mixed $default
- * @throws ServerException
* @return mixed
+ * @throws ServerException
*/
- public function json(string $key = null, $default = null)
+ public function json(?string $key = null, $default = null)
{
if (is_null($this->decoded)) {
if ($this->response->getHeaderLine('Content-Type') !== 'application/json') {
@@ -55,7 +56,7 @@ public function json(string $key = null, $default = null)
return $this->decoded;
}
- return array_get($this->decoded, $key, $default);
+ return Arr::get($this->decoded, $key, $default);
}
/**
diff --git a/src/Contract/DataFormatterInterface.php b/src/Contract/DataFormatterInterface.php
index 61c1df7..b980481 100644
--- a/src/Contract/DataFormatterInterface.php
+++ b/src/Contract/DataFormatterInterface.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Contract;
interface DataFormatterInterface
diff --git a/src/Contract/LoadBalancerInterface.php b/src/Contract/LoadBalancerInterface.php
index 6137920..5008c7a 100644
--- a/src/Contract/LoadBalancerInterface.php
+++ b/src/Contract/LoadBalancerInterface.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Contract;
use FriendsOfHyperf\Jet\LoadBalancer\Node;
diff --git a/src/Contract/PackerInterface.php b/src/Contract/PackerInterface.php
index 7fe52a3..6aee968 100644
--- a/src/Contract/PackerInterface.php
+++ b/src/Contract/PackerInterface.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Contract;
interface PackerInterface
diff --git a/src/Contract/PathGeneratorInterface.php b/src/Contract/PathGeneratorInterface.php
index 96cefb1..c7be033 100644
--- a/src/Contract/PathGeneratorInterface.php
+++ b/src/Contract/PathGeneratorInterface.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Contract;
interface PathGeneratorInterface
diff --git a/src/Contract/RegistryInterface.php b/src/Contract/RegistryInterface.php
index 65a2ca4..ea779be 100644
--- a/src/Contract/RegistryInterface.php
+++ b/src/Contract/RegistryInterface.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Contract;
use FriendsOfHyperf\Jet\LoadBalancer\Node;
diff --git a/src/Contract/TransporterInterface.php b/src/Contract/TransporterInterface.php
index 728c3e7..750d14c 100644
--- a/src/Contract/TransporterInterface.php
+++ b/src/Contract/TransporterInterface.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Contract;
interface TransporterInterface
diff --git a/src/DataFormatter/DataFormatter.php b/src/DataFormatter/DataFormatter.php
index 402bccd..343e74e 100644
--- a/src/DataFormatter/DataFormatter.php
+++ b/src/DataFormatter/DataFormatter.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\DataFormatter;
use FriendsOfHyperf\Jet\Contract\DataFormatterInterface;
diff --git a/src/DataFormatter/MultiplexDataFormatter.php b/src/DataFormatter/MultiplexDataFormatter.php
new file mode 100644
index 0000000..fe470ed
--- /dev/null
+++ b/src/DataFormatter/MultiplexDataFormatter.php
@@ -0,0 +1,73 @@
+ $id,
+ 'path' => $path,
+ 'data' => $params,
+ 'extra' => [],
+ 'context' => [],
+ ];
+ }
+
+ /**
+ * @param array $data
+ */
+ public function formatResponse($data): array
+ {
+ [$id, $result] = $data;
+
+ return [
+ 'id' => $id,
+ 'result' => $result,
+ 'context' => [],
+ ];
+ }
+
+ /**
+ * @param array $data
+ */
+ public function formatErrorResponse($data): array
+ {
+ [$id, $code, $message, $data] = $data;
+
+ if (isset($data) && $data instanceof \Throwable) {
+ $data = [
+ 'class' => get_class($data),
+ 'code' => $data->getCode(),
+ 'message' => $data->getMessage(),
+ ];
+ }
+
+ return [
+ 'id' => $id,
+ 'error' => [
+ 'code' => $code,
+ 'message' => $message,
+ 'data' => $data,
+ ],
+ 'context' => [],
+ ];
+ }
+}
diff --git a/src/Exception/ClientException.php b/src/Exception/ClientException.php
index 9c5ef4d..002868e 100644
--- a/src/Exception/ClientException.php
+++ b/src/Exception/ClientException.php
@@ -2,15 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Exception;
-class ClientException extends JetException
-{
-}
+class ClientException extends JetException {}
diff --git a/src/Exception/ConnectionException.php b/src/Exception/ConnectionException.php
index 79eb5ae..9a70138 100644
--- a/src/Exception/ConnectionException.php
+++ b/src/Exception/ConnectionException.php
@@ -2,15 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Exception;
-class ConnectionException extends JetException
-{
-}
+class ConnectionException extends JetException {}
diff --git a/src/Exception/ExceptionThrower.php b/src/Exception/ExceptionThrower.php
index 1e81b9a..56e13b0 100644
--- a/src/Exception/ExceptionThrower.php
+++ b/src/Exception/ExceptionThrower.php
@@ -2,30 +2,28 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
-namespace FriendsOfHyperf\Jet\Exception;
-use Throwable;
+namespace FriendsOfHyperf\Jet\Exception;
final class ExceptionThrower
{
/**
- * @var Throwable
+ * @var \Throwable
*/
private $throwable;
- public function __construct(Throwable $throwable)
+ public function __construct(\Throwable $throwable)
{
$this->throwable = $throwable;
}
- public function getThrowable(): Throwable
+ public function getThrowable(): \Throwable
{
return $this->throwable;
}
diff --git a/src/Exception/JetException.php b/src/Exception/JetException.php
index 94f6b8f..d58779e 100644
--- a/src/Exception/JetException.php
+++ b/src/Exception/JetException.php
@@ -2,17 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
-namespace FriendsOfHyperf\Jet\Exception;
-use RuntimeException;
+namespace FriendsOfHyperf\Jet\Exception;
-class JetException extends RuntimeException
-{
-}
+class JetException extends \RuntimeException {}
diff --git a/src/Exception/NoNodesAvailableException.php b/src/Exception/NoNodesAvailableException.php
new file mode 100644
index 0000000..6e71a78
--- /dev/null
+++ b/src/Exception/NoNodesAvailableException.php
@@ -0,0 +1,14 @@
+|\Throwable $exception
+ * @return TValue
+ * @throws \Throwable
+ */
+function throw_if($condition, $exception, ...$parameters)
+{
+ if ($condition) {
+ throw is_string($exception) ? new $exception(...$parameters) : $exception;
+ }
+
+ return $condition;
+}
+
+/**
+ * @template TValue
+ *
+ * @param TValue $value
+ * @return TValue
+ */
+function tap($value, ?callable $callback = null)
+{
+ if (is_null($callback)) {
+ return new class($value) {
+ public $target;
+
+ public function __construct($target)
+ {
+ $this->target = $target;
+ }
+
+ public function __call($method, $parameters)
+ {
+ $this->target->{$method}(...$parameters);
+
+ return $this->target;
+ }
+ };
+ }
+
+ $callback($value);
+
+ return $value;
+}
+
+/**
+ * @template TValue
+ * @template TReturn
+ *
+ * @param TValue $value
+ * @param null|(callable(TValue):TReturn) $callback
+ * @return ($callback is null ? TValue : TReturn)
+ */
+function with($value, ?callable $callback = null) // @phpstan-ignore-line
+{
+ return is_null($callback) ? $value : $callback($value);
+}
+
+/**
+ * @param mixed $value
+ * @return mixed
+ */
+function value($value)
+{
+ return $value instanceof \Closure ? $value() : $value;
+}
diff --git a/src/LoadBalancer/AbstractLoadBalancer.php b/src/LoadBalancer/AbstractLoadBalancer.php
index 9d1a752..2455498 100644
--- a/src/LoadBalancer/AbstractLoadBalancer.php
+++ b/src/LoadBalancer/AbstractLoadBalancer.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\LoadBalancer;
use FriendsOfHyperf\Jet\Contract\LoadBalancerInterface;
diff --git a/src/LoadBalancer/Node.php b/src/LoadBalancer/Node.php
index 06119fe..240acf2 100644
--- a/src/LoadBalancer/Node.php
+++ b/src/LoadBalancer/Node.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\LoadBalancer;
class Node
diff --git a/src/LoadBalancer/Random.php b/src/LoadBalancer/Random.php
index 9fcc25f..763c0e1 100644
--- a/src/LoadBalancer/Random.php
+++ b/src/LoadBalancer/Random.php
@@ -2,15 +2,17 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\LoadBalancer;
+use FriendsOfHyperf\Jet\Exception\NoNodesAvailableException;
+
class Random extends AbstractLoadBalancer
{
/**
@@ -19,7 +21,7 @@ class Random extends AbstractLoadBalancer
public function select(): Node
{
if (empty($this->nodes)) {
- throw new \RuntimeException('Cannot select any node from load balancer.');
+ throw new NoNodesAvailableException('Cannot select any node from load balancer.');
}
$key = array_rand($this->nodes);
diff --git a/src/LoadBalancer/RoundRobin.php b/src/LoadBalancer/RoundRobin.php
index beb1d35..ab0cfd7 100644
--- a/src/LoadBalancer/RoundRobin.php
+++ b/src/LoadBalancer/RoundRobin.php
@@ -2,16 +2,16 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\LoadBalancer;
-use RuntimeException;
+use FriendsOfHyperf\Jet\Exception\NoNodesAvailableException;
class RoundRobin extends AbstractLoadBalancer
{
@@ -28,7 +28,7 @@ public function select(): Node
$count = count($this->nodes);
if ($count <= 0) {
- throw new RuntimeException('Nodes missing.');
+ throw new NoNodesAvailableException('Nodes missing.');
}
$item = $this->nodes[self::$current % $count];
diff --git a/src/Metadata.php b/src/Metadata.php
index 62baba6..9113e49 100644
--- a/src/Metadata.php
+++ b/src/Metadata.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet;
use FriendsOfHyperf\Jet\Contract\DataFormatterInterface;
@@ -19,7 +19,6 @@
use FriendsOfHyperf\Jet\DataFormatter\DataFormatter;
use FriendsOfHyperf\Jet\Packer\JsonEofPacker;
use FriendsOfHyperf\Jet\PathGenerator\PathGenerator;
-use RuntimeException;
class Metadata
{
@@ -68,11 +67,22 @@ class Metadata
*/
protected $timeout = 3;
- public function __construct(string $name)
+ public function __construct(string $name = '')
{
$this->name = $name;
}
+ /**
+ * @return static
+ */
+ public function withName(string $name)
+ {
+ $clone = clone $this;
+ $clone->name = $name;
+
+ return $clone;
+ }
+
/**
* Get name.
* @return string
@@ -82,12 +92,27 @@ public function getName()
return $this->name;
}
+ /**
+ * @return static
+ */
+ public function withProtocol(string $protocol)
+ {
+ $clone = clone $this;
+ $clone->protocol = $protocol;
+
+ return $clone;
+ }
+
/**
* Set protocol.
+ * @deprecated use withProtocol instead, will be removed in v4.0
+ * @return $this
*/
public function setProtocol(string $protocol)
{
$this->protocol = $protocol;
+
+ return $this;
}
/**
@@ -99,12 +124,27 @@ public function getProtocol()
return $this->protocol;
}
+ /**
+ * @return static
+ */
+ public function withTransporter(TransporterInterface $transporter)
+ {
+ $clone = clone $this;
+ $clone->transporter = $transporter;
+
+ return $clone;
+ }
+
/**
* Set transporter.
+ * @deprecated use withTransporter instead, will be removed in v4.0
+ * @return $this
*/
public function setTransporter(TransporterInterface $transporter)
{
$this->transporter = $transporter;
+
+ return $this;
}
/**
@@ -121,15 +161,30 @@ public function getTransporter()
return $this->registry->getTransporter($this->name, $this->protocol, $this->timeout);
}
- throw new RuntimeException('Transporter not registered yet.');
+ throw new \RuntimeException('Transporter not registered yet.');
+ }
+
+ /**
+ * @return static
+ */
+ public function withPacker(PackerInterface $packer)
+ {
+ $clone = clone $this;
+ $clone->packer = $packer;
+
+ return $clone;
}
/**
* Set packer.
+ * @deprecated use withPacker instead, will be removed in v4.0
+ * @return $this
*/
public function setPacker(PackerInterface $packer)
{
$this->packer = $packer;
+
+ return $this;
}
/**
@@ -145,12 +200,27 @@ public function getPacker()
return $this->packer;
}
+ /**
+ * @return static
+ */
+ public function withDataFormatter(DataFormatterInterface $dataFormatter)
+ {
+ $clone = clone $this;
+ $clone->dataFormatter = $dataFormatter;
+
+ return $clone;
+ }
+
/**
* Set data formatter.
+ * @deprecated use withDataFormatter instead, will be removed in v4.0
+ * @return $this
*/
public function setDataFormatter(DataFormatterInterface $dataFormatter)
{
$this->dataFormatter = $dataFormatter;
+
+ return $this;
}
/**
@@ -166,12 +236,26 @@ public function getDataFormatter()
return $this->dataFormatter;
}
+ /**
+ * @return static
+ */
+ public function withPathGenerator(PathGeneratorInterface $pathGenerator)
+ {
+ $clone = clone $this;
+ $clone->pathGenerator = $pathGenerator;
+
+ return $clone;
+ }
+
/**
* Set path generator.
+ * @return $this
*/
public function setPathGenerator(PathGeneratorInterface $pathGenerator)
{
$this->pathGenerator = $pathGenerator;
+
+ return $this;
}
/**
@@ -187,12 +271,27 @@ public function getPathGenerator()
return $this->pathGenerator;
}
+ /**
+ * @return static
+ */
+ public function withRegistry(RegistryInterface $registry)
+ {
+ $clone = clone $this;
+ $clone->registry = $registry;
+
+ return $clone;
+ }
+
/**
* Set registry.
+ * @deprecated use withRegistry instead, will be removed in v4.0
+ * @return $this
*/
public function setRegistry(RegistryInterface $registry)
{
$this->registry = $registry;
+
+ return $this;
}
/**
@@ -204,12 +303,26 @@ public function getRegistry()
return $this->registry;
}
+ /**
+ * @return static
+ */
+ public function withTries(int $tries)
+ {
+ $clone = clone $this;
+ $clone->tries = $tries;
+
+ return $clone;
+ }
+
/**
* Set tries.
+ * @return $this
*/
public function setTries(int $tries)
{
$this->tries = $tries;
+
+ return $this;
}
/**
@@ -221,12 +334,26 @@ public function getTries()
return (int) $this->tries;
}
+ /**
+ * @return static
+ */
+ public function withTimeout(int $timeout)
+ {
+ $clone = clone $this;
+ $clone->timeout = $timeout;
+
+ return $clone;
+ }
+
/**
* Set timeout.
+ * @return $this
*/
public function setTimeout(int $timeout)
{
$this->timeout = $timeout;
+
+ return $this;
}
/**
diff --git a/src/MetadataManager.php b/src/MetadataManager.php
new file mode 100644
index 0000000..d86ae69
--- /dev/null
+++ b/src/MetadataManager.php
@@ -0,0 +1,33 @@
+
+ */
+ protected static $metadata = [];
+
+ public static function register(string $name, Metadata $metadata)
+ {
+ static::$metadata[$name] = $metadata;
+ }
+
+ /**
+ * @return null|Metadata
+ */
+ public static function get(string $name)
+ {
+ return isset(static::$metadata[$name]) ? clone static::$metadata[$name] : null;
+ }
+}
diff --git a/src/Packer/JsonEofPacker.php b/src/Packer/JsonEofPacker.php
index 9d7d05c..2c144d0 100644
--- a/src/Packer/JsonEofPacker.php
+++ b/src/Packer/JsonEofPacker.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Packer;
use FriendsOfHyperf\Jet\Contract\PackerInterface;
diff --git a/src/Packer/JsonLengthPacker.php b/src/Packer/JsonLengthPacker.php
index 5ef9af0..7062241 100644
--- a/src/Packer/JsonLengthPacker.php
+++ b/src/Packer/JsonLengthPacker.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Packer;
use FriendsOfHyperf\Jet\Contract\PackerInterface;
diff --git a/src/Packer/JsonMultiplexPacker.php b/src/Packer/JsonMultiplexPacker.php
new file mode 100644
index 0000000..328b54d
--- /dev/null
+++ b/src/Packer/JsonMultiplexPacker.php
@@ -0,0 +1,41 @@
+ array_get($node, 'Checks.1.Type'),
- 'protocol' => array_get($node, 'Service.Meta.Protocol'),
+ 'type' => Arr::get($node, 'Checks.1.Type'),
+ 'protocol' => Arr::get($node, 'Service.Meta.Protocol'),
]
);
}
@@ -146,7 +149,7 @@ public function getTransporter(string $service, ?string $protocol = null, int $t
$nodes = $this->getServiceNodes($service, $protocol);
if (count($nodes) <= 0) {
- throw new RuntimeException('Service nodes not found!');
+ throw new \RuntimeException('Service nodes not found!');
}
$serviceBalancer = new RoundRobin($nodes);
diff --git a/src/RegistryManager.php b/src/RegistryManager.php
index d22e9ad..2393129 100644
--- a/src/RegistryManager.php
+++ b/src/RegistryManager.php
@@ -2,18 +2,17 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet;
use FriendsOfHyperf\Jet\Contract\RegistryInterface;
use FriendsOfHyperf\Jet\Exception\JetException;
-use InvalidArgumentException;
class RegistryManager
{
@@ -36,13 +35,13 @@ public static function get($name = self::DEFAULT)
/**
* @param string $name
* @param RegistryInterface $registry
- * @throws InvalidArgumentException
+ * @throws \InvalidArgumentException
* @throws JetException
*/
public static function register($name, $registry, bool $force = false)
{
- if (! ($registry instanceof RegistryInterface)) {
- throw new InvalidArgumentException('$registry must be instanceof RegistryInterface');
+ if (! $registry instanceof RegistryInterface) {
+ throw new \InvalidArgumentException('$registry must be instanceof RegistryInterface');
}
if (! $force && self::isRegistered($name)) {
diff --git a/src/ServiceManager.php b/src/ServiceManager.php
index 9bc4057..7363d93 100644
--- a/src/ServiceManager.php
+++ b/src/ServiceManager.php
@@ -2,16 +2,14 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
-namespace FriendsOfHyperf\Jet;
-use InvalidArgumentException;
+namespace FriendsOfHyperf\Jet;
class ServiceManager
{
@@ -37,7 +35,7 @@ public static function isRegistered(string $service)
}
/**
- * @throws InvalidArgumentException
+ * @throws \InvalidArgumentException
*/
public static function register(string $service, Metadata $metadata)
{
diff --git a/src/Support/Arr.php b/src/Support/Arr.php
new file mode 100644
index 0000000..afc1d8e
--- /dev/null
+++ b/src/Support/Arr.php
@@ -0,0 +1,111 @@
+offsetExists($key);
+ }
+
+ return array_key_exists($key, $array);
+ }
+
+ /**
+ * @param mixed $value
+ * @return bool
+ */
+ public static function accessible($value)
+ {
+ return is_array($value) || $value instanceof \ArrayAccess;
+ }
+}
diff --git a/src/Support/Str.php b/src/Support/Str.php
new file mode 100644
index 0000000..e17bb4b
--- /dev/null
+++ b/src/Support/Str.php
@@ -0,0 +1,87 @@
+ $replace
+ * @param string $subject
+ * @return string
+ */
+ public static function replaceArray($search, $replace, $subject)
+ {
+ foreach ($replace as $value) {
+ $subject = self::replaceFirst($search, $value, $subject);
+ }
+
+ return $subject;
+ }
+}
diff --git a/src/Support/UserAgent.php b/src/Support/UserAgent.php
new file mode 100644
index 0000000..89a8a0b
--- /dev/null
+++ b/src/Support/UserAgent.php
@@ -0,0 +1,39 @@
+host = $host;
- $this->port = $port;
- $this->config = array_merge_recursive($config, [
- 'headers' => [
- 'Content-Type' => 'application/json',
- 'X-Real-Ip' => $_SERVER['SERVER_ADDR'] ?? '',
- 'X-Forwarded-For' => $_SERVER['REMOTE_ADDR'] ?? '',
- 'User-Agent' => ClientFactory::getUserAgent(),
- ],
+ parent::__construct($host, $port);
+
+ $this->config = array_replace([
'http_errors' => false,
- ]);
+ 'timeout' => $this->timeout,
+ ], $config);
+ $this->config['headers'] = array_replace([
+ 'Content-Type' => 'application/json',
+ 'X-Real-Ip' => $_SERVER['SERVER_ADDR'] ?? '',
+ 'X-Forwarded-For' => $_SERVER['REMOTE_ADDR'] ?? '',
+ 'User-Agent' => UserAgent::get(),
+ ], $config['headers'] ?? []);
}
public function send(string $data)
diff --git a/src/Transporter/MultiplexRpcTransporter.php b/src/Transporter/MultiplexRpcTransporter.php
new file mode 100644
index 0000000..5b89b04
--- /dev/null
+++ b/src/Transporter/MultiplexRpcTransporter.php
@@ -0,0 +1,84 @@
+client, false);
+
+ while (true) {
+ $header = $this->readBytes(4);
+
+ $unpacked = unpack('Nlength', $header);
+ $length = $unpacked['length'];
+
+ if ($length < 4) {
+ throw new RecvFailedException(sprintf('Invalid package length: %d', $length));
+ }
+ $body = $this->readBytes($length);
+ if (in_array($body, [self::PING, self::PONG], true)) {
+ continue;
+ }
+
+ return $header . $body;
+ }
+ }
+
+ /**
+ * @throws \Exception
+ */
+ private function readBytes(int $length): string
+ {
+ $buffer = '';
+
+ while (strlen($buffer) < $length) {
+ $read = [$this->client];
+ $write = null;
+ $except = null;
+
+ $selected = stream_select($read, $write, $except, $this->timeout);
+ if ($selected === false) {
+ throw new \RuntimeException('Failed to select stream.');
+ }
+
+ if ($selected === 0) {
+ throw new RecvFailedException('Receive timeout.');
+ }
+
+ foreach ($read as $stream) {
+ /** @var false|string $chunk */
+ $chunk = fread($stream, $length - strlen($buffer));
+
+ if ($chunk === false) {
+ throw new RecvFailedException('Receive failed.');
+ }
+
+ if ($chunk === '' && feof($stream)) {
+ throw new ConnectionException('Connection was closed.');
+ }
+
+ $buffer .= $chunk;
+ }
+ }
+
+ return $buffer;
+ }
+}
diff --git a/src/Transporter/StreamSocketTransporter.php b/src/Transporter/StreamSocketTransporter.php
index bd3c68e..76e98af 100644
--- a/src/Transporter/StreamSocketTransporter.php
+++ b/src/Transporter/StreamSocketTransporter.php
@@ -2,22 +2,20 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Transporter;
-use Exception;
use FriendsOfHyperf\Jet\Exception\ConnectionException;
use FriendsOfHyperf\Jet\Exception\ExceptionThrower;
use FriendsOfHyperf\Jet\Exception\RecvFailedException;
-use InvalidArgumentException;
-use RuntimeException;
-use Throwable;
+
+use function FriendsOfHyperf\Jet\retry;
class StreamSocketTransporter extends AbstractTransporter
{
@@ -26,11 +24,6 @@ class StreamSocketTransporter extends AbstractTransporter
*/
protected $client;
- /**
- * @var float
- */
- protected $timeout;
-
/**
* @var bool
*/
@@ -42,8 +35,8 @@ public function __destruct()
}
/**
- * @throws InvalidArgumentException
- * @throws RuntimeException
+ * @throws \InvalidArgumentException
+ * @throws \RuntimeException
*/
public function send(string $data)
{
@@ -52,14 +45,14 @@ public function send(string $data)
}
/**
- * @throws Throwable
* @return string
+ * @throws \Throwable
*/
public function recv()
{
try {
return $this->receive();
- } catch (Throwable $e) {
+ } catch (\Throwable $e) {
$this->close();
throw $e;
}
@@ -71,19 +64,19 @@ public function recv()
public function receive()
{
$buf = '';
- $timeout = 1000;
+ $timeoutMs = $this->timeout > 0 ? $this->timeout * 1000 : 1000;
stream_set_blocking($this->client, false);
// The maximum number of retries is 12, and 1000 microseconds is the minimum waiting time.
// The waiting time is doubled each time until the server writes data to the buffer.
// Usually, the data can be obtained within 1 microsecond.
- $result = retry(12, function () use (&$buf, &$timeout) {
+ $result = retry(12, function () use (&$buf, &$timeoutMs) {
$read = [$this->client];
$write = null;
$except = null;
- while (stream_select($read, $write, $except, 0, $timeout)) {
+ while (stream_select($read, $write, $except, 0, $timeoutMs)) {
foreach ($read as $r) {
$res = fread($r, 8192);
if (feof($r)) {
@@ -94,7 +87,7 @@ public function receive()
}
if (! $buf) {
- $timeout *= 2;
+ $timeoutMs *= 2;
throw new RecvFailedException('No data was received');
}
@@ -110,9 +103,9 @@ public function receive()
}
/**
- * @throws InvalidArgumentException
- * @throws Exception
- * @return (string|int)[]
+ * @return array{string, int}
+ * @throws \InvalidArgumentException
+ * @throws \Exception
*/
protected function getTarget()
{
@@ -123,36 +116,39 @@ protected function getTarget()
}
if (! $node->host || ! $node->port) {
- throw new InvalidArgumentException(sprintf('Invalid host %s or port %s.', $node->host, $node->port));
+ throw new \InvalidArgumentException(sprintf('Invalid host %s or port %s.', $node->host, $node->port));
}
return [$node->host, $node->port];
}
/**
- * @throws InvalidArgumentException
- * @throws Exception
+ * @throws \InvalidArgumentException
+ * @throws \Exception
*/
protected function connect()
{
if ($this->isConnected) {
return;
}
+
if ($this->client) {
fclose($this->client);
unset($this->client);
}
- [$host, $port] = $this->getTarget();
+ retry(5, function() {
+ [$host, $port] = $this->getTarget();
- $client = stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, $this->timeout);
+ $client = stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, $this->timeout);
- if ($client === false) {
- throw new ConnectionException(sprintf('[%d] %s', $errno, $errstr));
- }
+ if ($client === false) {
+ throw new ConnectionException(sprintf('[%d] %s', $errno, $errstr));
+ }
- $this->client = $client;
- $this->isConnected = true;
+ $this->client = $client;
+ $this->isConnected = true;
+ });
}
protected function close()
diff --git a/src/helpers.php b/src/helpers.php
deleted file mode 100644
index 367fb96..0000000
--- a/src/helpers.php
+++ /dev/null
@@ -1,283 +0,0 @@
-target = $target;
- }
-
- public function __call($method, $parameters)
- {
- $this->target->{$method}(...$parameters);
-
- return $this->target;
- }
- };
- }
-
- $callback($value);
-
- return $value;
- }
-}
-
-if (! function_exists('with')) {
- /**
- * @param mixed $value
- * @return mixed
- */
- function with($value, callable $callback = null)
- {
- return is_null($callback) ? $value : $callback($value);
- }
-}
-
-if (! function_exists('str_snake')) {
- /**
- * @param string $delimiter
- * @return string
- */
- function str_snake(string $value, $delimiter = '_')
- {
- if (! ctype_lower($value)) {
- $value = preg_replace('/\s+/u', '', ucwords($value));
- $value = str_lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
- }
-
- return $value;
- }
-}
-
-if (! function_exists('str_lower')) {
- /**
- * @return string
- */
- function str_lower(string $value)
- {
- return mb_strtolower($value, 'UTF-8');
- }
-}
-
-if (! function_exists('str_studly')) {
- /**
- * @return string
- */
- function str_studly(string $value, string $gap = '')
- {
- $value = ucwords(str_replace(['-', '_'], ' ', $value));
-
- return str_replace(' ', $gap, $value);
- }
-}
-
-if (! function_exists('str_replace_first')) {
- /**
- * @return string
- */
- function str_replace_first(string $search, string $replace, string $subject)
- {
- if ($search == '') {
- return $subject;
- }
-
- $position = strpos($subject, $search);
-
- if ($position !== false) {
- return substr_replace($subject, $replace, $position, strlen($search));
- }
-
- return $subject;
- }
-}
-
-if (! function_exists('str_replace_array')) {
- /**
- * @return string
- */
- function str_replace_array(string $search, array $replace, string $subject)
- {
- foreach ($replace as $value) {
- $subject = str_replace_first($search, (string) $value, $subject);
- }
-
- return $subject;
- }
-}
-
-if (! function_exists('value')) {
- /**
- * @param mixed $value
- * @return mixed
- */
- function value($value)
- {
- return $value instanceof Closure ? $value() : $value;
- }
-}
-
-if (! function_exists('array_get')) {
- /**
- * Get an item from an array using "dot" notation.
- *
- * @param array|\ArrayAccess $array
- * @param null|int|string $key
- * @param mixed $default
- */
- function array_get($array, $key = null, $default = null)
- {
- if (is_null($key)) {
- return $array;
- }
-
- if (isset($array[$key])) {
- return $array[$key];
- }
-
- if (! is_string($key) || strpos($key, '.') === false) {
- return $array[$key] ?? value($default);
- }
-
- foreach (explode('.', $key) as $segment) {
- if (array_accessible($array) && array_exists($array, $segment)) {
- $array = $array[$segment];
- } else {
- return value($default);
- }
- }
-
- return $array;
- }
-}
-
-if (! function_exists('array_has')) {
- /**
- * Check if an item or items exist in an array using "dot" notation.
- *
- * @param array|\ArrayAccess $array
- * @param null|array|string $keys
- */
- function array_has($array, $keys)
- {
- if (is_null($keys)) {
- return false;
- }
-
- $keys = (array) $keys;
-
- if (! $array || $keys === []) {
- return false;
- }
-
- foreach ($keys as $key) {
- $subKeyArray = $array;
-
- if (array_exists($array, $key)) {
- continue;
- }
-
- foreach (explode('.', $key) as $segment) {
- if (array_accessible($subKeyArray) && array_exists($subKeyArray, $segment)) {
- $subKeyArray = $subKeyArray[$segment];
- } else {
- return false;
- }
- }
- }
-
- return true;
- }
-}
-
-if (! function_exists('array_exists')) {
- /**
- * @param mixed $array
- * @param int|string $key
- * @return bool
- */
- function array_exists($array, $key)
- {
- if ($array instanceof ArrayAccess) {
- return $array->offsetExists($key);
- }
-
- return array_key_exists($key, $array);
- }
-}
-
-if (! function_exists('array_accessible')) {
- /**
- * @param mixed $value
- * @return bool
- */
- function array_accessible($value)
- {
- return is_array($value) || $value instanceof ArrayAccess;
- }
-}
diff --git a/tests/ClientTest.php b/tests/ClientTest.php
index 25c3251..2c1ada5 100644
--- a/tests/ClientTest.php
+++ b/tests/ClientTest.php
@@ -2,16 +2,20 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Tests;
use FriendsOfHyperf\Jet\ClientFactory;
+use FriendsOfHyperf\Jet\DataFormatter\MultiplexDataFormatter;
+use FriendsOfHyperf\Jet\Metadata;
+use FriendsOfHyperf\Jet\MetadataManager;
+use FriendsOfHyperf\Jet\Packer\JsonMultiplexPacker;
use FriendsOfHyperf\Jet\RegistryManager;
/**
@@ -62,4 +66,34 @@ public function testCalculatorServiceByStreamSocketTransporter()
$this->assertSame($a + $b, $client->add($a, $b));
}
+
+ public function testCalculatorServiceByMultiplexRpcTransporter()
+ {
+ $client = ClientFactory::create(
+ $this->service,
+ $this->createMultiplexRpcTransporter(),
+ new JsonMultiplexPacker(),
+ new MultiplexDataFormatter()
+ );
+
+ $a = rand(1, 99);
+ $b = rand(1, 99);
+
+ $this->assertSame($a + $b, $client->add($a, $b));
+ }
+
+ public function testMetadataManager()
+ {
+ MetadataManager::register(
+ $name = 'test',
+ (new Metadata())->withTransporter($this->createGuzzleHttpTransporter())
+ );
+
+ $client = ClientFactory::create($this->service, $name);
+
+ $a = rand(1, 99);
+ $b = rand(1, 99);
+
+ $this->assertSame($a + $b, $client->add($a, $b));
+ }
}
diff --git a/tests/RegistryTest.php b/tests/RegistryTest.php
index 9862c5e..0e7fb26 100644
--- a/tests/RegistryTest.php
+++ b/tests/RegistryTest.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Tests;
use FriendsOfHyperf\Jet\Contract\RegistryInterface;
diff --git a/tests/TestCase.php b/tests/TestCase.php
index a7aaf55..2c625e0 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -2,17 +2,18 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
+
namespace FriendsOfHyperf\Jet\Tests;
use FriendsOfHyperf\Jet\Registry\ConsulRegistry;
use FriendsOfHyperf\Jet\Transporter\GuzzleHttpTransporter;
+use FriendsOfHyperf\Jet\Transporter\MultiplexRpcTransporter;
use FriendsOfHyperf\Jet\Transporter\StreamSocketTransporter;
/**
@@ -37,6 +38,12 @@ class TestCase extends \PHPUnit\Framework\TestCase
private $jsonrpcHttpTimeout;
+ private $jsonrpcLengthCheckHost;
+
+ private $jsonrpcLengthCheckPort;
+
+ private $jsonrpcLengthCheckTimeout;
+
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
@@ -51,6 +58,10 @@ public function __construct($name = null, array $data = [], $dataName = '')
$this->jsonrpcHttpHost = $_ENV['JSONRPC_HTTP_HOST'] ?? '127.0.0.1';
$this->jsonrpcHttpPort = (int) ($_ENV['JSONRPC_HTTP_PORT'] ?? 9502);
$this->jsonrpcHttpTimeout = (int) ($_ENV['JSONRPC_HTTP_TIMEOUT'] ?? 2);
+
+ $this->jsonrpcLengthCheckHost = $_ENV['JSONRPC_LENGTH_CHECK_HOST'] ?? '127.0.0.1';
+ $this->jsonrpcLengthCheckPort = (int) ($_ENV['JSONRPC_LENGTH_CHECK_PORT'] ?? 9504);
+ $this->jsonrpcLengthCheckTimeout = (int) ($_ENV['JSONRPC_LENGTH_CHECK_TIMEOUT'] ?? 2);
}
public function createGuzzleHttpTransporter()
@@ -63,6 +74,11 @@ public function createStreamSocketTransporter()
return new StreamSocketTransporter($this->jsonrpcHost, $this->jsonrpcPort, $this->jsonrpcTimeout);
}
+ public function createMultiplexRpcTransporter()
+ {
+ return new MultiplexRpcTransporter($this->jsonrpcLengthCheckHost, $this->jsonrpcLengthCheckPort, $this->jsonrpcLengthCheckTimeout);
+ }
+
protected function createRegistry()
{
return new ConsulRegistry(['uri' => $this->consulUri, 'timeout' => $this->consulTimeout]);
diff --git a/tests/register.php b/tests/register.php
index 88b009c..3ac119c 100644
--- a/tests/register.php
+++ b/tests/register.php
@@ -2,12 +2,11 @@
declare(strict_types=1);
/**
- * This file is part of jet.
+ * This file is part of friendsofhyperf/jet.
*
* @link https://github.com/friendsofhyperf/jet
* @document https://github.com/friendsofhyperf/jet/blob/main/README.md
* @contact huangdijia@gmail.com
- * @license https://github.com/friendsofhyperf/jet/blob/main/LICENSE
*/
require_once __DIR__ . '/../vendor/autoload.php';