namespace seekat\API\Call;
-use Exception;
use http\{
Client, Client\Request, Client\Response
};
-use React\Promise\ExtendedPromiseInterface;
+use Psr\Log\LoggerInterface;
use seekat\API;
-use SplObserver;
-use SplSubject;
-class Deferred extends \React\Promise\Deferred implements SplObserver
+final class Deferred
{
/**
* The response importer
*/
private $cache;
+ /**
+ * @var LoggerInterface
+ */
+ private $logger;
+
/**
* The executed request
*
*/
private $response;
+ /**
+ * @var mixed
+ */
+ private $promise;
+
+ /**
+ * @var \Closure
+ */
+ private $resolve;
+
+ /**
+ * @var \Closure
+ */
+ private $reject;
+
+ /**
+ * @var \Closure
+ */
+ private $update;
+
/**
* Create a deferred promise for the response of $request
*
* @param Cache\Service $cache
*/
function __construct(API $api, Request $request, Cache\Service $cache = null) {
- parent::__construct(function ($resolve, $reject) {
- return $this->cancel($resolve, $reject);
- });
-
$this->request = $request;
$this->client = $api->getClient();
+ $this->logger = $api->getLogger();
$this->result = new Result($api);
$this->cache = new Cache($cache);
+ $future = $api->getFuture();
+ $context = $future->createContext(function() {
+ if ($this->response) {
+ /* we did finish in the meantime */
+ $this->complete();
+ } else {
+ $this->client->dequeue($this->request);
+ ($this->reject)("Cancelled");
+ }
+ });
+ $this->promise = $future->getPromise($context);
+ $this->resolve = API\Future\resolver($future, $context);
+ $this->reject = API\Future\rejecter($future, $context);
+ }
+
+ function __invoke() {
if ($this->cache->load($this->request, $cached)) {
- $api->getLogger()->info("deferred -> cached", [
- "method" => $request->getRequestMethod(),
- "url" => $request->getRequestUrl(),
+ $this->logger->info("deferred -> cached", [
+ "method" => $this->request->getRequestMethod(),
+ "url" => $this->request->getRequestUrl(),
]);
$this->response = $cached;
- $this->complete(
- [$this, "resolve"],
- [$this, "reject"]
- );
+ $this->complete();
} else {
- $this->client->attach($this);
$this->client->enqueue($this->request, function(Response $response) use($cached) {
if ($response->getResponseCode() == 304) {
$this->response = $cached;
} else {
$this->response = $response;
}
- $this->complete(
- [$this, "resolve"],
- [$this, "reject"]
- );
+ $this->complete();
return true;
});
- $api->getLogger()->info("deferred -> enqueued", [
- "method" => $request->getRequestMethod(),
- "url" => $request->getRequestUrl(),
+ $this->logger->info("deferred -> enqueued", [
+ "method" => $this->request->getRequestMethod(),
+ "url" => $this->request->getRequestUrl(),
]);
/* start off */
$this->client->once();
}
- }
- /**
- * Progress observer
- *
- * Import the response's data on success and resolve the promise.
- *
- * @param SplSubject $client The observed HTTP client
- * @param Request $request The request which generated the update
- * @param object $progress The progress information
- */
- function update(SplSubject $client, Request $request = null, $progress = null) {
- if ($request !== $this->request) {
- return;
- }
-
- $this->notify((object) compact("client", "request", "progress"));
+ return $this->promise;
}
/**
* Completion callback
- * @param callable $resolve
- * @param callable $reject
*/
- private function complete(callable $resolve, callable $reject) {
- $this->client->detach($this);
-
+ private function complete() {
if ($this->response) {
try {
$api = ($this->result)($this->response);
$this->cache->save($this->request, $this->response);
- $resolve($api);
- } catch (Exception $e) {
- $reject($e);
+ ($this->resolve)($api);
+ } catch (\Throwable $e) {
+ ($this->reject)($e);
}
} else {
- $reject($this->client->getTransferInfo($this->request)->error);
+ ($this->reject)($this->client->getTransferInfo($this->request)->error);
}
}
- /**
- * Cancellation callback
- * @param callable $resolve
- * @param callable $reject
- */
- private function cancel(callable $resolve, callable $reject) {
- /* did we finish in the meantime? */
- if ($this->response) {
- $this->complete($resolve, $reject);
- } else {
- $this->client->detach($this);
- $this->client->dequeue($this->request);
- $reject("Cancelled");
- }
- }
}