appwrite/src/Appwrite/GraphQL/CoroutinePromiseAdapter.php

104 lines
3 KiB
PHP
Raw Normal View History

2022-04-05 13:48:51 +00:00
<?php
namespace Appwrite\GraphQL;
use GraphQL\Error\InvariantViolation;
use GraphQL\Executor\Promise\Promise;
use GraphQL\Executor\Promise\PromiseAdapter;
use GraphQL\Utils\Utils;
2022-05-02 06:24:51 +00:00
use Swoole\Coroutine\Channel;
use function Co\go;
2022-04-05 13:48:51 +00:00
2022-04-08 07:04:15 +00:00
class CoroutinePromiseAdapter implements PromiseAdapter
2022-04-05 13:48:51 +00:00
{
public function isThenable($value): bool
{
2022-04-22 05:49:46 +00:00
return $value instanceof CoroutinePromise;
2022-04-05 13:48:51 +00:00
}
public function convertThenable($thenable): Promise
{
2022-04-22 05:49:46 +00:00
if (!$thenable instanceof CoroutinePromise) {
2022-04-05 13:48:51 +00:00
throw new InvariantViolation('Expected instance of SwoolePromise, got ' . Utils::printSafe($thenable));
}
return new Promise($thenable, $this);
}
public function then(Promise $promise, ?callable $onFulfilled = null, ?callable $onRejected = null): Promise
{
2022-04-08 07:04:15 +00:00
/** @var CoroutinePromise $adoptedPromise */
2022-04-05 13:48:51 +00:00
$adoptedPromise = $promise->adoptedPromise;
return new Promise($adoptedPromise->then($onFulfilled, $onRejected), $this);
}
public function create(callable $resolver): Promise
{
2022-04-08 07:04:15 +00:00
$promise = new CoroutinePromise();
2022-04-05 13:48:51 +00:00
try {
$resolver(
[$promise, 'resolve'],
[$promise, 'reject'],
);
} catch (\Throwable $e) {
$promise->reject($e);
}
return new Promise($promise, $this);
}
public function createFulfilled($value = null): Promise
{
2022-04-08 07:04:15 +00:00
$promise = new CoroutinePromise();
2022-04-05 13:48:51 +00:00
return new Promise($promise->resolve($value), $this);
}
public function createRejected($reason): Promise
{
2022-04-08 07:04:15 +00:00
$promise = new CoroutinePromise();
2022-04-05 13:48:51 +00:00
return new Promise($promise->reject($reason), $this);
}
public function all(array $promisesOrValues): Promise
{
2022-05-02 06:24:51 +00:00
$all = new CoroutinePromise(function (callable $resolve, callable $reject) use ($promisesOrValues) {
$ticks = count($promisesOrValues);
$firstError = null;
$channel = new Channel($ticks);
$result = [];
$key = 0;
2022-04-05 13:48:51 +00:00
2022-05-02 06:24:51 +00:00
foreach ($promisesOrValues as $promiseOrValue) {
if (!$promiseOrValue instanceof Promise) {
$result[$key] = $promiseOrValue;
$channel->push(true);
}
$promiseOrValue->then(function ($value) use ($key, &$result, $channel) {
$result[$key] = $value;
$channel->push(true);
}, function ($error) use ($channel, &$firstError) {
$channel->push(true);
if ($firstError === null) {
$firstError = $error;
}
});
$key++;
}
2022-04-05 13:48:51 +00:00
2022-05-02 06:24:51 +00:00
while ($ticks--) {
$channel->pop();
2022-04-26 07:49:36 +00:00
}
2022-05-02 06:24:51 +00:00
$channel->close();
if ($firstError !== null) {
$reject($firstError);
return;
}
$resolve($result);
});
2022-04-05 13:48:51 +00:00
return new Promise($all, $this);
}
}