Skip to content

Commit

Permalink
Merge branch 'improved-async'
Browse files Browse the repository at this point in the history
  • Loading branch information
denpamusic committed Sep 14, 2018
2 parents ed7716d + 16b51ce commit d9f22d0
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 140 deletions.
28 changes: 10 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,15 @@ $satoshi = \Denpa\Bitcoin\to_satoshi($bitcoin);
```
To send asynchronous request, add Async to method name:
```php
use Denpa\Bitcoin\BitcoindResponse;

$promise = $bitcoind->getBlockAsync(
$bitcoind->getBlockAsync(
'000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
function (BitcoindResponse $success) {
//
function ($response) {
// success
},
function (\Exception $exception) {
//
function ($exception) {
// error
}
);

$promise->wait();
```

You can also send requests using request method:
Expand Down Expand Up @@ -131,20 +127,16 @@ $txid = $result->get();
```
or requestAsync method for asynchronous calls:
```php
use Denpa\Bitcoin\BitcoindResponse;

$promise = $bitcoind->requestAsync(
$bitcoind->requestAsync(
'getBlock',
'000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
function (BitcoindResponse $success) {
//
function ($response) {
// success
},
function (\Exception $exception) {
//
function ($exception) {
// error
}
);

$promise->wait();
```

## Multi-Wallet RPC
Expand Down
135 changes: 74 additions & 61 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Promise;
use Psr\Http\Message\ResponseInterface;

class Client
Expand All @@ -25,6 +26,13 @@ class Client
*/
protected $config;

/**
* Array of GuzzleHttp promises.
*
* @var array
*/
protected $promises = [];

/**
* URL path.
*
Expand Down Expand Up @@ -60,6 +68,18 @@ public function __construct($config = [])
]);
}

/**
* Wait for all promises on object destruction.
*
* @return void
*/
public function __destruct()
{
if (!empty($this->promises)) {
Promise\settle($this->promises)->wait();
}
}

/**
* Gets http client config.
*
Expand Down Expand Up @@ -124,10 +144,8 @@ public function wallet($name)
public function request($method, ...$params)
{
try {
$response = $this->client->request(
'POST',
$this->path,
['json' => $this->makeJson($method, $params)]);
$response = $this->client
->post($this->path, $this->makeJson($method, $params));

if ($response->hasError()) {
// throw exception on error
Expand All @@ -136,17 +154,7 @@ public function request($method, ...$params)

return $response;
} catch (RequestException $exception) {
if (
$exception->hasResponse() &&
$exception->getResponse()->hasError()
) {
throw new Exceptions\BitcoindException($exception->getResponse()->error());
}

throw new Exceptions\ClientException(
$exception->getMessage(),
$exception->getCode()
);
throw $this->handleException($exception);
}
}

Expand All @@ -155,31 +163,29 @@ public function request($method, ...$params)
*
* @param string $method
* @param mixed $params
* @param callable|null $onFullfiled
* @param callable|null $onRejected
* @param callable|null $fulfilled
* @param callable|null $rejected
*
* @return \GuzzleHttp\Promise\Promise
*/
public function requestAsync(
$method,
$params = [],
callable $onFullfiled = null,
callable $onRejected = null)
callable $fulfilled = null,
callable $rejected = null)
{
$promise = $this->client->requestAsync(
'POST',
$this->path,
['json' => $this->makeJson($method, $params)]
);
$promise = $this->client
->postAsync($this->path, $this->makeJson($method, $params));

$promise->then(
function (ResponseInterface $response) use ($onFullfiled) {
$this->asyncFulfilled($response, $onFullfiled);
},
function (RequestException $exception) use ($onRejected) {
$this->asyncRejected($exception, $onRejected);
}
);
$promise->then(function ($response) use ($fulfilled) {
$this->onSuccess($response, $fulfilled);
});

$promise->otherwise(function ($exception) use ($rejected) {
$this->onError($exception, $rejected);
});

$this->promises[] = $promise;

return $promise;
}
Expand All @@ -194,9 +200,8 @@ function (RequestException $exception) use ($onRejected) {
*/
public function __call($method, array $params = [])
{
$method = str_ireplace('async', '', $method, $count);
if ($count > 0) {
return $this->requestAsync($method, ...$params);
if (strtolower(substr($method, -5)) == 'async') {
return $this->requestAsync(substr($method, 0, -5), ...$params);
}

return $this->request($method, ...$params);
Expand Down Expand Up @@ -326,9 +331,11 @@ protected function parseUrl($config)
protected function makeJson($method, $params = [])
{
return [
'method' => strtolower($method),
'params' => (array) $params,
'id' => $this->rpcId++,
'json' => [
'method' => strtolower($method),
'params' => (array) $params,
'id' => $this->rpcId++,
],
];
}

Expand All @@ -340,15 +347,14 @@ protected function makeJson($method, $params = [])
*
* @return void
*/
protected function asyncFulfilled(ResponseInterface $response, callable $callback = null)
protected function onSuccess(ResponseInterface $response, callable $callback = null)
{
$error = null;
if ($response->hasError()) {
$error = new Exceptions\BitcoindException($response->error());
}
if (!is_null($callback)) {
if ($response->hasError()) {
$response = new Exceptions\BitcoindException($response->error());
}

if (is_callable($callback)) {
$callback($error ?: $response);
$callback($response);
}
}

Expand All @@ -360,26 +366,33 @@ protected function asyncFulfilled(ResponseInterface $response, callable $callbac
*
* @return void
*/
protected function asyncRejected(RequestException $exception, callable $callback = null)
protected function onError(RequestException $exception, callable $callback = null)
{
if (
$exception->hasResponse() &&
$exception->getResponse()->hasError()
) {
$exception = new Exceptions\BitcoindException(
$exception->getResponse()->error()
);
if (!is_null($callback)) {
$callback($this->handleException($exception));
}
}

if ($exception instanceof RequestException) {
$exception = new Exceptions\ClientException(
$exception->getMessage(),
$exception->getCode()
);
}
/**
* Handles exceptions.
*
* @param \Exception $exception
*
* @return \Exception
*/
protected function handleException($exception)
{
if ($exception->hasResponse()) {
$response = $exception->getResponse();

if (is_callable($callback)) {
$callback($exception);
if ($response->hasError()) {
return new Exceptions\BitcoindException($response->error());
}
}

return new Exceptions\ClientException(
$exception->getMessage(),
$exception->getCode()
);
}
}
Loading

0 comments on commit d9f22d0

Please sign in to comment.