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 <noreply@anthropic.com>
This commit is contained in:
Jake Barnby
2026-01-22 20:20:11 +13:00
co-authored by Claude Opus 4.5
parent 9ed02eb194
commit f79e846cb2
@@ -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) {