3 namespace seekat\API\Call
;
5 use http\
{Client
, Client\Request
, Client\Response
};
6 use Psr\Log\LoggerInterface
;
10 private Result
$result;
11 private Client
$client;
12 private LoggerInterface
$logger;
16 * The promised response
18 private ?Response
$response = null;
23 private object $promise;
24 private \Closure
$resolve;
25 private \Closure
$reject;
28 * Create a deferred promise for the response of $request
30 * @param API $api The endpoint of the request
31 * @param Request $request The request to execute
33 function __construct(API
$api, private readonly Request
$request) {
34 $this->result
= new Result($api);
35 $this->client
= $api->getClient();
36 $this->logger
= $api->getLogger();
37 $this->cache
= new Cache($this->logger
, $api->getCache());
39 $future = $api->getFuture();
40 $context = $future->createContext(function() {
41 if ($this->response
) {
42 /* we did finish in the meantime */
45 $this->client
->dequeue($this->request
);
46 ($this->reject
)("Cancelled");
49 $this->promise
= $future->getPromise($context);
50 $this->resolve
= $future->resolver($context);
51 $this->reject
= $future->rejecter($context);
55 if (!$this->cached($cached)) {
56 $this->refresh($cached);
59 return $this->promise
;
65 * @param Response $cached
68 private function cached(Response
&$cached = null) : bool {
69 $fresh = $this->cache
->load($this->request
, $cachedResponse);
71 if (!$cachedResponse) {
74 $cached = $cachedResponse;
76 $this->logger
->info("deferred -> cached", [
77 "method" => $this->request
->getRequestMethod(),
78 "url" => $this->request
->getRequestUrl(),
83 $this->logger
->info("cached -> stale", [
84 "method" => $this->request
->getRequestMethod(),
85 "url" => $this->request
->getRequestUrl(),
91 $this->response
= $cached;
92 $this->complete("cached");
96 private function refresh(Response
$cached = null) : void
{
97 $this->client
->enqueue($this->request
, function(Response
$response) use($cached) {
98 $this->response
= $response;
103 $this->logger
->info(($cached ?
"stale" : "deferred") . " -> enqueued", [
104 "method" => $this->request
->getRequestMethod(),
105 "url" => $this->request
->getRequestUrl(),
109 $this->client
->once();
113 * Completion callback
115 private function complete(string $by = "enqueued") : void
{
116 $this->logger
->info("complete -> $by");
118 if ($this->response
) {
119 $this->logger
->info("$by -> response", [
120 "url" => $this->request
->getRequestUrl(),
121 "info" => $this->response
->getInfo(),
125 $this->cache
->update($this->request
, $this->response
);
126 ($this->resolve
)(($this->result
)($this->response
));
127 } catch (\Throwable
$e) {
128 $this->logger
->warning("$by -> cache", ["exception" => $e]);
132 $info = $this->client
->getTransferInfo($this->request
);
134 $this->logger
->warning("$by -> no response", [
135 "url" => $this->request
->getRequestUrl(),
139 ($this->reject
)($info->error
);