1
0
mirror of https://github.com/danog/amp.git synced 2024-12-03 09:57:51 +01:00

Rethrow in loop from any Awaitable failure

This commit is contained in:
Aaron Piotrowski 2020-11-01 11:19:17 -06:00
parent 3ebd44ee09
commit 0838d483fe
No known key found for this signature in database
GPG Key ID: ADD1EF783EDE9EEB
10 changed files with 55 additions and 78 deletions

View File

@ -25,13 +25,6 @@ final class Failure implements Promise
*/
public function onResolve(callable $onResolved): void
{
Loop::defer(function () use ($onResolved): void {
/** @var mixed $result */
$result = $onResolved($this->exception, null);
if ($result instanceof Promise) {
Promise\rethrow($result);
}
});
Loop::defer(fn() => $onResolved($this->exception, null));
}
}

View File

@ -36,14 +36,7 @@ final class Placeholder
return;
}
Loop::defer(function () use ($onResolved): void {
/** @var mixed $result */
$result = $onResolved(null, $this->result);
if ($result instanceof Promise) {
Promise\rethrow($result);
}
});
Loop::defer(fn() => $onResolved(null, $this->result));
return;
}
@ -127,15 +120,7 @@ final class Placeholder
return;
}
Loop::defer(function () use ($onResolved): void {
/** @var mixed $result */
$result = $onResolved(null, $this->result);
$onResolved = null; // allow garbage collection of $onResolved, to catch any exceptions from destructors
if ($result instanceof Promise) {
Promise\rethrow($result);
}
});
Loop::defer(fn() => $onResolved(null, $this->result));
}
/**

View File

@ -67,11 +67,15 @@ final class ResolutionQueue
try {
$result = $callback($exception, $value);
if ($result instanceof Promise) {
Promise\rethrow($result);
if ($result instanceof \Awaitable) {
$result->onResolve(static function (?\Throwable $exception): void {
if ($exception) {
throw $exception;
}
});
}
} catch (\Throwable $exception) {
Loop::defer(static function () use ($exception) {
Loop::defer(static function () use ($exception): void {
throw $exception;
});
}

View File

@ -2,9 +2,6 @@
namespace Amp\Loop;
use Amp\Promise;
use function Amp\Promise\rethrow;
/**
* Event loop driver which implements all basic operations to allow interoperability.
*
@ -688,6 +685,20 @@ abstract class DriverFoundation implements Driver
($this->errorHandler)($exception);
}
/**
* Attaches a callback that forwards the Awaitable failure reason to the loop error handler.
*
* @param \Awaitable $awaitable
*/
protected function rethrow(\Awaitable $awaitable): void
{
$awaitable->onResolve(function (?\Throwable $exception): void {
if ($exception) {
$this->error($exception);
}
});
}
/**
* @return bool True if no enabled and referenced watchers remain in the loop.
*/
@ -730,8 +741,8 @@ abstract class DriverFoundation implements Driver
/** @var mixed $result */
$result = ($watcher->callback)($watcher->id, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);

View File

@ -2,9 +2,7 @@
namespace Amp\Loop;
use Amp\Promise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
final class EvDriver extends DriverFoundation
{
@ -59,8 +57,8 @@ final class EvDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -88,8 +86,8 @@ final class EvDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -108,8 +106,8 @@ final class EvDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);

View File

@ -2,9 +2,7 @@
namespace Amp\Loop;
use Amp\Promise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
final class EventDriver extends DriverFoundation
{
@ -55,8 +53,8 @@ final class EventDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -82,8 +80,8 @@ final class EventDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -101,8 +99,8 @@ final class EventDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);

View File

@ -2,9 +2,7 @@
namespace Amp\Loop;
use Amp\Promise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
final class NativeDriver extends DriverFoundation
{
@ -103,8 +101,8 @@ final class NativeDriver extends DriverFoundation
// Execute the timer.
$result = ($watcher->callback)($watcher->id, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -167,8 +165,8 @@ final class NativeDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -192,8 +190,8 @@ final class NativeDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -349,8 +347,8 @@ final class NativeDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);

View File

@ -2,10 +2,6 @@
namespace Amp\Loop;
use Amp\Coroutine;
use Amp\Promise;
use function Amp\Promise\rethrow;
final class UvDriver extends DriverFoundation
{
/** @var resource|\UVLoop A uv_loop resource created with uv_loop_new() */
@ -65,8 +61,8 @@ final class UvDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $resource, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -95,8 +91,8 @@ final class UvDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);
@ -115,8 +111,8 @@ final class UvDriver extends DriverFoundation
try {
$result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
if ($result instanceof Promise) {
rethrow($result);
if ($result instanceof \Awaitable) {
$this->rethrow($result);
}
} catch (\Throwable $exception) {
$this->error($exception);

View File

@ -37,7 +37,7 @@ final class Success implements Promise
try {
$this->value = null;
} catch (\Throwable $e) {
Loop::defer(static function () use ($e) {
Loop::defer(static function () use ($e): void {
throw $e;
});
}
@ -48,12 +48,6 @@ final class Success implements Promise
*/
public function onResolve(callable $onResolved): void
{
Loop::defer(function () use ($onResolved): void {
$result = $onResolved(null, $this->value);
if ($result instanceof Promise) {
Promise\rethrow($result);
}
});
Loop::defer(fn() => $onResolved(null, $this->value));
}
}

View File

@ -262,7 +262,7 @@ namespace Amp\Promise
$promise = adapt($promise);
}
$promise->onResolve(static function ($exception) {
$promise->onResolve(static function (?\Throwable $exception): void {
if ($exception) {
throw $exception;
}