Instead of relying on then() callbacks which may not fire correctly,
poll the adopted promise state directly using Swoole Coroutine::sleep
for proper yielding. Each promise is waited on in its own coroutine.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This avoids scheduling issues where spawned coroutines don't get a
chance to run before the main coroutine continues waiting.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace busy-waiting in then() with proper callback queuing:
- Store waiting callbacks in array when promise is pending
- When promise resolves/rejects, process all waiting callbacks
- Run callbacks in coroutines for proper async execution
- This eliminates deadlocks from busy-wait polling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add public resolve() and reject() methods to Promise class
- Create combined promise without executor (no coroutine spawned)
- Use direct resolve/reject calls instead of captured callbacks
- This ensures the promise can be settled regardless of coroutine timing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use callback-based approach similar to graphql-php's SyncPromiseAdapter:
- Create a combined promise and capture resolve/reject callbacks
- Register then() callbacks on each input promise
- Resolve when all callbacks have fired
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use Swoole Coroutine::sleep for proper coroutine yielding instead of
callback-based completion tracking
- Spawn a coroutine for each promise to wait for its completion
- Use Channel for synchronization between coroutines
- Add public accessors to Promise class for state checking
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use callback-based counting instead of channel synchronization to track
promise completion. Work directly with GQLPromise objects and use their
then() method which properly chains through the adapter to the underlying
SwoolePromise.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of reimplementing the promise aggregation logic, extract adopted
promises from GQLPromise wrappers and delegate to SwoolePromise::all()
which already handles the coroutine synchronization properly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of extracting adopted promises and delegating to SwoolePromise::all(),
implement the batch handling logic directly to properly work with GQLPromise
wrappers. Uses Swoole Channel for synchronization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The graphql-php executor passes both promises and plain values to
the PromiseAdapter::all() method. Updated SwoolePromise::all() to
properly handle plain values by storing them directly without
attempting to call ->then() on them.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>