summaryrefslogtreecommitdiff
path: root/server/vendor/guzzlehttp/promises
diff options
context:
space:
mode:
authorroot <root@kabir-PC>2016-03-23 11:31:51 +0100
committerroot <root@kabir-PC>2016-03-23 11:31:51 +0100
commita26989103d70fb0dd3ff6834de107cae246778c3 (patch)
tree0f243c83b790ffb57f19261fc2a509131f6776ce /server/vendor/guzzlehttp/promises
parent1342db60283cb61a1c3810993575d35b9fb33ac0 (diff)
parent6e78d76f887d1149ea85bfb06db7ee7ad7435f5a (diff)
Merge branch 'develop' of https://github.com/manzerbredes/istic-openstack into develop
Diffstat (limited to 'server/vendor/guzzlehttp/promises')
-rw-r--r--server/vendor/guzzlehttp/promises/CHANGELOG.md6
-rw-r--r--server/vendor/guzzlehttp/promises/src/EachPromise.php20
-rw-r--r--server/vendor/guzzlehttp/promises/src/Promise.php27
-rw-r--r--server/vendor/guzzlehttp/promises/src/TaskQueue.php1
-rw-r--r--server/vendor/guzzlehttp/promises/src/functions.php8
-rw-r--r--server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php48
-rw-r--r--server/vendor/guzzlehttp/promises/tests/PromiseTest.php12
7 files changed, 100 insertions, 22 deletions
diff --git a/server/vendor/guzzlehttp/promises/CHANGELOG.md b/server/vendor/guzzlehttp/promises/CHANGELOG.md
index 4031cb8..3871ac7 100644
--- a/server/vendor/guzzlehttp/promises/CHANGELOG.md
+++ b/server/vendor/guzzlehttp/promises/CHANGELOG.md
@@ -1,5 +1,11 @@
# CHANGELOG
+## 1.1.0 - 2016-03-07
+
+* Update EachPromise to prevent recurring on a iterator when advancing, as this
+ could trigger fatal generator errors.
+* Update Promise to allow recursive waiting without unwrapping exceptions.
+
## 1.0.3 - 2015-10-15
* Update EachPromise to immediately resolve when the underlying promise iterator
diff --git a/server/vendor/guzzlehttp/promises/src/EachPromise.php b/server/vendor/guzzlehttp/promises/src/EachPromise.php
index 5918429..0344686 100644
--- a/server/vendor/guzzlehttp/promises/src/EachPromise.php
+++ b/server/vendor/guzzlehttp/promises/src/EachPromise.php
@@ -24,6 +24,9 @@ class EachPromise implements PromisorInterface
/** @var Promise */
private $aggregate;
+ /** @var bool */
+ private $mutex;
+
/**
* Configuration hash can include the following key value pairs:
*
@@ -81,6 +84,7 @@ class EachPromise implements PromisorInterface
private function createPromise()
{
+ $this->mutex = false;
$this->aggregate = new Promise(function () {
reset($this->pending);
if (empty($this->pending) && !$this->iterable->valid()) {
@@ -169,11 +173,21 @@ class EachPromise implements PromisorInterface
private function advanceIterator()
{
+ // Place a lock on the iterator so that we ensure to not recurse,
+ // preventing fatal generator errors.
+ if ($this->mutex) {
+ return false;
+ }
+
+ $this->mutex = true;
+
try {
$this->iterable->next();
+ $this->mutex = false;
return true;
} catch (\Exception $e) {
$this->aggregate->reject($e);
+ $this->mutex = false;
return false;
}
}
@@ -186,9 +200,11 @@ class EachPromise implements PromisorInterface
}
unset($this->pending[$idx]);
- $this->advanceIterator();
- if (!$this->checkIfFinished()) {
+ // Only refill pending promises if we are not locked, preventing the
+ // EachPromise to recursively invoke the provided iterator, which
+ // cause a fatal error: "Cannot resume an already running generator"
+ if ($this->advanceIterator() && !$this->checkIfFinished()) {
// Add more pending promises if possible.
$this->refillPending();
}
diff --git a/server/vendor/guzzlehttp/promises/src/Promise.php b/server/vendor/guzzlehttp/promises/src/Promise.php
index c2cf969..86820b2 100644
--- a/server/vendor/guzzlehttp/promises/src/Promise.php
+++ b/server/vendor/guzzlehttp/promises/src/Promise.php
@@ -61,17 +61,19 @@ class Promise implements PromiseInterface
{
$this->waitIfPending();
- if (!$unwrap) {
- return null;
- }
+ $inner = $this->result instanceof PromiseInterface
+ ? $this->result->wait($unwrap)
+ : $this->result;
- if ($this->result instanceof PromiseInterface) {
- return $this->result->wait($unwrap);
- } elseif ($this->state === self::FULFILLED) {
- return $this->result;
- } else {
- // It's rejected so "unwrap" and throw an exception.
- throw exception_for($this->result);
+ if ($unwrap) {
+ if ($this->result instanceof PromiseInterface
+ || $this->state === self::FULFILLED
+ ) {
+ return $inner;
+ } else {
+ // It's rejected so "unwrap" and throw an exception.
+ throw exception_for($inner);
+ }
}
}
@@ -257,11 +259,10 @@ class Promise implements PromiseInterface
$this->waitList = null;
foreach ($waitList as $result) {
- descend:
$result->waitIfPending();
- if ($result->result instanceof Promise) {
+ while ($result->result instanceof Promise) {
$result = $result->result;
- goto descend;
+ $result->waitIfPending();
}
}
}
diff --git a/server/vendor/guzzlehttp/promises/src/TaskQueue.php b/server/vendor/guzzlehttp/promises/src/TaskQueue.php
index 5026363..39fe5bb 100644
--- a/server/vendor/guzzlehttp/promises/src/TaskQueue.php
+++ b/server/vendor/guzzlehttp/promises/src/TaskQueue.php
@@ -56,6 +56,7 @@ class TaskQueue
*/
public function run()
{
+ /** @var callable $task */
while ($task = array_shift($this->queue)) {
$task();
}
diff --git a/server/vendor/guzzlehttp/promises/src/functions.php b/server/vendor/guzzlehttp/promises/src/functions.php
index 89c6569..2fe61b7 100644
--- a/server/vendor/guzzlehttp/promises/src/functions.php
+++ b/server/vendor/guzzlehttp/promises/src/functions.php
@@ -146,9 +146,9 @@ function inspect(PromiseInterface $promise)
'value' => $promise->wait()
];
} catch (RejectionException $e) {
- return ['state' => 'rejected', 'reason' => $e->getReason()];
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
} catch (\Exception $e) {
- return ['state' => 'rejected', 'reason' => $e];
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
}
}
@@ -304,10 +304,10 @@ function settle($promises)
return each(
$promises,
function ($value, $idx) use (&$results) {
- $results[$idx] = ['state' => 'fulfilled', 'value' => $value];
+ $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
},
function ($reason, $idx) use (&$results) {
- $results[$idx] = ['state' => 'rejected', 'reason' => $reason];
+ $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
}
)->then(function () use (&$results) {
ksort($results);
diff --git a/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php b/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php
index 0a0a851..08af2a0 100644
--- a/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php
+++ b/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php
@@ -39,8 +39,8 @@ class EachPromiseTest extends \PHPUnit_Framework_TestCase
public function testIsWaitable()
{
- $a = new Promise(function () use (&$a) { $a->resolve('a'); });
- $b = new Promise(function () use (&$b) { $b->resolve('b'); });
+ $a = $this->createSelfResolvingPromise('a');
+ $b = $this->createSelfResolvingPromise('b');
$called = [];
$each = new EachPromise([$a, $b], [
'fulfilled' => function ($value) use (&$called) { $called[] = $value; }
@@ -54,7 +54,7 @@ class EachPromiseTest extends \PHPUnit_Framework_TestCase
public function testCanResolveBeforeConsumingAll()
{
$called = 0;
- $a = new Promise(function () use (&$a) { $a->resolve('a'); });
+ $a = $this->createSelfResolvingPromise('a');
$b = new Promise(function () { $this->fail(); });
$each = new EachPromise([$a, $b], [
'fulfilled' => function ($value, $idx, Promise $aggregate) use (&$called) {
@@ -291,4 +291,46 @@ class EachPromiseTest extends \PHPUnit_Framework_TestCase
}
$this->assertEquals(range(0, 9), $results);
}
+
+ private function createSelfResolvingPromise($value)
+ {
+ $p = new Promise(function () use (&$p, $value) {
+ $p->resolve($value);
+ });
+
+ return $p;
+ }
+
+ public function testMutexPreventsGeneratorRecursion()
+ {
+ $results = $promises = [];
+ for ($i = 0; $i < 20; $i++) {
+ $p = $this->createSelfResolvingPromise($i);
+ $pending[] = $p;
+ $promises[] = $p;
+ }
+
+ $iter = function () use (&$promises, &$pending) {
+ foreach ($promises as $promise) {
+ // Resolve a promises, which will trigger the then() function,
+ // which would cause the EachPromise to try to add more
+ // promises to the queue. Without a lock, this would trigger
+ // a "Cannot resume an already running generator" fatal error.
+ if ($p = array_pop($pending)) {
+ $p->wait();
+ }
+ yield $promise;
+ }
+ };
+
+ $each = new EachPromise($iter(), [
+ 'concurrency' => 5,
+ 'fulfilled' => function ($r) use (&$results, &$pending) {
+ $results[] = $r;
+ }
+ ]);
+
+ $each->promise()->wait();
+ $this->assertCount(20, $results);
+ }
}
diff --git a/server/vendor/guzzlehttp/promises/tests/PromiseTest.php b/server/vendor/guzzlehttp/promises/tests/PromiseTest.php
index 946c627..599d8ae 100644
--- a/server/vendor/guzzlehttp/promises/tests/PromiseTest.php
+++ b/server/vendor/guzzlehttp/promises/tests/PromiseTest.php
@@ -172,6 +172,18 @@ class PromiseTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('Whoop', $p->wait());
}
+ public function testWaitsOnAPromiseChainEvenWhenNotUnwrapped()
+ {
+ $p2 = new Promise(function () use (&$p2) {
+ $p2->reject('Fail');
+ });
+ $p = new Promise(function () use ($p2, &$p) {
+ $p->resolve($p2);
+ });
+ $p->wait(false);
+ $this->assertSame(Promise::REJECTED, $p2->getState());
+ }
+
public function testCannotCancelNonPending()
{
$p = new Promise();