diff --git a/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php b/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php index b3b31dc6fe..4f484ac127 100644 --- a/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php +++ b/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php @@ -5,6 +5,7 @@ namespace Appwrite\GraphQL\Promises\Adapter; use Appwrite\GraphQL\Promises\Adapter; use Appwrite\Promises\Swoole as SwoolePromise; use GraphQL\Executor\Promise\Promise as GQLPromise; +use Swoole\Coroutine\Channel; class Swoole extends Adapter { @@ -46,40 +47,50 @@ class Swoole extends Adapter return; } - $result = \array_fill(0, $count, null); - $pending = $count; - $rejected = false; + $result = []; + $error = null; + $channel = new Channel($count); foreach ($promisesOrValues as $index => $promiseOrValue) { if ($promiseOrValue instanceof GQLPromise) { - $promiseOrValue->then( - function ($value) use ($index, &$result, &$pending, &$rejected, $resolve) { - if ($rejected) { - return; - } - $result[$index] = $value; - $pending--; - if ($pending === 0) { - \ksort($result); - $resolve($result); - } - }, - function ($error) use (&$rejected, $reject) { - if (!$rejected) { - $rejected = true; - $reject($error); + // Spawn a coroutine to wait for each promise + \go(function () use ($promiseOrValue, $index, &$result, &$error, $channel) { + /** @var SwoolePromise $adoptedPromise */ + $adoptedPromise = $promiseOrValue->adoptedPromise; + + // Wait for the promise to resolve using a polling approach + while ($adoptedPromise->isPending()) { + \Swoole\Coroutine::sleep(0.001); + } + + if ($adoptedPromise->isFulfilled()) { + $result[$index] = $adoptedPromise->getResult(); + } else { + if ($error === null) { + $error = $adoptedPromise->getResult(); } } - ); + $channel->push(true); + }); } else { $result[$index] = $promiseOrValue; - $pending--; - if ($pending === 0 && !$rejected) { - \ksort($result); - $resolve($result); - } + $channel->push(true); } } + + // Wait for all promises to complete + for ($i = 0; $i < $count; $i++) { + $channel->pop(); + } + $channel->close(); + + if ($error !== null) { + $reject($error); + return; + } + + \ksort($result); + $resolve($result); }); } } diff --git a/src/Appwrite/Promises/Promise.php b/src/Appwrite/Promises/Promise.php index a6b1aa79d5..8de17c13c8 100644 --- a/src/Appwrite/Promises/Promise.php +++ b/src/Appwrite/Promises/Promise.php @@ -167,7 +167,7 @@ abstract class Promise * * @return boolean */ - protected function isPending(): bool + public function isPending(): bool { return $this->state == self::STATE_PENDING; } @@ -177,7 +177,7 @@ abstract class Promise * * @return boolean */ - protected function isFulfilled(): bool + public function isFulfilled(): bool { return $this->state == self::STATE_FULFILLED; } @@ -187,8 +187,18 @@ abstract class Promise * * @return boolean */ - protected function isRejected(): bool + public function isRejected(): bool { return $this->state == self::STATE_REJECTED; } + + /** + * Get the result value (only valid after promise is settled) + * + * @return mixed + */ + public function getResult(): mixed + { + return $this->result; + } }