From f79e846cb225da89d082aba265d5cda5b1bc517d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 22 Jan 2026 20:20:11 +1300 Subject: [PATCH] Fix GraphQL hanging by running both promise queues The graphql-php library uses its own SyncPromise queue for Deferred resolution, which is separate from our SwoolePromise queue. The wait() method now runs both queues to ensure all deferred tasks are processed. Co-Authored-By: Claude Opus 4.5 --- .../GraphQL/Promises/Adapter/Swoole.php | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php b/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php index b4107d70ac..e17dbc1d9a 100644 --- a/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php +++ b/src/Appwrite/GraphQL/Promises/Adapter/Swoole.php @@ -4,6 +4,7 @@ namespace Appwrite\GraphQL\Promises\Adapter; use Appwrite\GraphQL\Promises\Adapter; use Appwrite\Promises\Swoole as SwoolePromise; +use GraphQL\Executor\Promise\Adapter\SyncPromise; use GraphQL\Executor\Promise\Promise as GQLPromise; class Swoole extends Adapter @@ -20,13 +21,27 @@ class Swoole extends Adapter /** @var SwoolePromise $swoolePromise */ $swoolePromise = $promise->adoptedPromise; - // Run any pending queue tasks (for compatibility with graphql-php's deferred execution) - $taskQueue = SwoolePromise::getQueue(); - while ( - $swoolePromise->state === SwoolePromise::PENDING - && !$taskQueue->isEmpty() - ) { - SwoolePromise::runQueue(); + // Run both graphql-php's SyncPromise queue and our SwoolePromise queue + // graphql-php's Deferred uses SyncPromise::getQueue() internally + $syncQueue = SyncPromise::getQueue(); + $swooleQueue = SwoolePromise::getQueue(); + + while ($swoolePromise->state === SwoolePromise::PENDING) { + // Run graphql-php's SyncPromise queue first (handles Deferred) + if (!$syncQueue->isEmpty()) { + SyncPromise::runQueue(); + continue; + } + + // Then run our SwoolePromise queue + if (!$swooleQueue->isEmpty()) { + SwoolePromise::runQueue(); + continue; + } + + // Both queues empty but promise still pending - this shouldn't happen + // in a properly resolved promise chain + break; } if ($swoolePromise->state === SwoolePromise::FULFILLED) {