Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions Executor/Promise/Adapter/ReactPromiseAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,34 +41,43 @@ public function convertThenable($thenable)
/**
* Synchronously wait when promise completes.
*
* @param Promise $promise
* @param Promise $promise
* @param callable $onProgress
*
* @return ExecutionResult
*
* @throws \Exception
*/
public function wait(Promise $promise)
public function wait(Promise $promise, callable $onProgress = null)
{
if (!$this->isThenable($promise)) {
return;
throw new \InvalidArgumentException(sprintf('The "%s" method must be call with compatible a Promise.', __METHOD__));
}
$wait = true;
$resolvedValue = null;
$exception = null;
/** @var \React\Promise\PromiseInterface $reactPromise */
$reactPromise = $promise->adoptedPromise;

$reactPromise->then(function ($values) use (&$resolvedValue, &$wait) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment inside this block to explain why

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe adding usleep(1) would make it less CPU intensive without sacrificing the performance

$resolvedValue = $values;
$wait = false;
}, function ($reason) use (&$exception, &$wait) {
$exception = $reason;
$wait = false;
});

// wait until promise resolution
while ($wait) {
$reactPromise->then(function ($values) use (&$resolvedValue, &$wait) {
$resolvedValue = $values;
$wait = false;
}, function ($reason) use (&$exception, &$wait) {
$exception = $reason;
$wait = false;
});
if (null !== $onProgress) {
$onProgress();
}
// less CPU intensive without sacrificing the performance
usleep(5);
}

if ($exception instanceof \Exception) {
/** @var \Exception|null $exception */
if (null !== $exception) {
throw $exception;
}

Expand Down
2 changes: 0 additions & 2 deletions ExpressionLanguage/AuthorizationExpressionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ function () {
'isFullyAuthenticated',
function () {
return '$container->get(\'security.authorization_checker\')->isGranted(\'IS_AUTHENTICATED_FULLY\')';
},
function () {
}
),

Expand Down
72 changes: 72 additions & 0 deletions Tests/Executor/Promise/Adapter/ReactPromiseAdapterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/*
* This file is part of the OverblogGraphQLBundle package.
*
* (c) Overblog <http://github.com/overblog/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Overblog\GraphQLBundle\Tests\Error;

use GraphQL\Executor\Promise\Promise;
use Overblog\GraphQLBundle\Executor\Promise\Adapter\ReactPromiseAdapter;
use Symfony\Component\Process\PhpProcess;

class ReactPromiseAdapterTest extends \PHPUnit_Framework_TestCase
{
/** @var ReactPromiseAdapter */
private $adapter;

public function setUp()
{
$this->adapter = new ReactPromiseAdapter();
}

/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage The "Overblog\GraphQLBundle\Executor\Promise\Adapter\ReactPromiseAdapter::wait" method must be call with compatible a Promise.
*/
public function testWaitWithNotSupportedPromise()
{
$noSupportedPromise = new Promise(new \stdClass(), $this->adapter);
$this->adapter->wait($noSupportedPromise);
}

/**
* @expectedException \Exception
* @expectedExceptionMessage Promise has been rejected!
*/
public function testWaitRejectedPromise()
{
$rejected = $this->adapter->createRejected(new \Exception('Promise has been rejected!'));
$this->adapter->wait($rejected);
}

public function testWaitAsyncPromise()
{
$output = 'OK!';
$process = new PhpProcess(<<<EOF
<?php
usleep(30);
echo '$output';
EOF
);

$promise = $this->adapter->create(function (callable $resolve) use (&$process) {
$process->start(function () use ($resolve, &$process) {
$output = $process->getOutput();
$resolve($output);
});
});

$this->assertEquals(
$output,
$this->adapter->wait($promise, function () use (&$process) {
$process->wait();
})
);
}
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"webonyx/graphql-php": "^0.9.0"
},
"suggest": {
"twig/twig": "If you want to use graphiQL."
"twig/twig": "If you want to use graphiQL.",
"react/promise": "To use ReactPHP promise adapter"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^1.11",
Expand Down