Skip to content

Instantly share code, notes, and snippets.

@arnaud-lb
Created January 31, 2017 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnaud-lb/a2a5a5480bbd80013f756ff968282936 to your computer and use it in GitHub Desktop.
Save arnaud-lb/a2a5a5480bbd80013f756ff968282936 to your computer and use it in GitHub Desktop.
<?php
use React\Promise\PromiseInterface;
class UnhandledRejectionTracer
{
private $promises;
private $unhandledPromiseCallback;
public function __construct($unhandledPromiseCallback)
{
$this->promises = [];
$this->unhandledPromiseCallback = $unhandledPromiseCallback;
}
/**
* Called when a promise is instanciated
*/
public function instanciated(PromiseInterface $promise, $reason = null)
{
$hash = spl_object_hash($promise);
// Providing the trace as a string, not as an Exception instance,
// because this could trigger PHP GC issues; e.g. making a variable
// rechable again during a __destructor call.
$exception = new \Exception();
$trace = "Promise started here: \n" . $exception->getTraceAsString();
$this->promises[$hash] = [
'trace' => $trace,
'reason' => $reason ? $this->stringifyReason($reason) : null,
];
}
/**
* Called when a promise has been handled
*/
public function handled(PromiseInterface $promise)
{
$hash = spl_object_hash($promise);
if (!isset($this->promises[$hash])) {
return;
}
unset($this->promises[$hash]);
}
/**
* Called when a promise is destroyed
*/
public function destroyed(PromiseInterface $promise)
{
$hash = spl_object_hash($promise);
$this->notifyUnhandledPromise($this->promises[$hash]);
unset($this->promises[$hash]);
}
/**
* When called at the end of a program, this method returns an array of
* promises than haven't been handled. They may not have been destroyed
* because they are still reachable, or because PHP didn't called their
* destructor.
*/
public function getRemainingPromises()
{
return $this->promises;
}
private function notifyUnhandledPromise(array $promiseInfo)
{
if (null !== $cb = $this->unhandledPromiseCallback) {
call_user_func($cb, $promiseInfo);
}
}
private function stringifyReason($reason)
{
if (is_object($reason) && method_exists($reason, '__toString')) {
return (string) $reason;
}
return json_encode($reason);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment