Proper async traces
This commit is contained in:
parent
db40848866
commit
379cd0f247
@ -58,20 +58,15 @@ final class Coroutine implements Promise, \ArrayAccess
|
||||
/** @var mixed Promise success value when executing next coroutine step, null at all other times. */
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* Generator trace.
|
||||
*
|
||||
* @var Trace
|
||||
*/
|
||||
private $trace;
|
||||
/** @var ?self Reference to coroutine that started this coroutine */
|
||||
private $parentCoroutine;
|
||||
|
||||
/**
|
||||
* @param \Generator $generator
|
||||
*/
|
||||
public function __construct(\Generator $generator, Trace $trace = null)
|
||||
public function __construct(\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
//$this->trace = $trace ?? new Trace(\debug_backtrace());
|
||||
|
||||
try {
|
||||
$yielded = $this->generator->current();
|
||||
@ -92,24 +87,13 @@ final class Coroutine implements Promise, \ArrayAccess
|
||||
return;
|
||||
}
|
||||
if ($yielded instanceof \Generator) {
|
||||
/*if ($this->generator->valid()) {
|
||||
$reflection = new ReflectionGenerator($this->generator);
|
||||
$trace = new Trace(
|
||||
[[
|
||||
'file' => $reflection->getExecutingFile(),
|
||||
'line' => $reflection->getExecutingLine(),
|
||||
'function' => $reflection->getFunction()->getName(),
|
||||
]],
|
||||
$this->trace
|
||||
);
|
||||
} else {
|
||||
$trace = $this->trace;
|
||||
}
|
||||
$yielded = new self($yielded, $trace);*/
|
||||
$yielded = new self($yielded);
|
||||
} else {
|
||||
$yielded = $this->generator->send($yielded);
|
||||
}
|
||||
if ($yielded instanceof self) {
|
||||
$yielded->parentCoroutine = $this;
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$this->fail($exception);
|
||||
@ -133,7 +117,7 @@ final class Coroutine implements Promise, \ArrayAccess
|
||||
do {
|
||||
if ($this->exception) {
|
||||
// Throw exception at current execution point.
|
||||
$yielded = $this->generator->throw($this->exception);
|
||||
$yielded = $this->throw($this->exception);
|
||||
} else {
|
||||
// Send the new value and execute to next yield statement.
|
||||
$yielded = $this->generator->send($this->value);
|
||||
@ -163,6 +147,9 @@ final class Coroutine implements Promise, \ArrayAccess
|
||||
$yielded = $this->generator->send($yielded);
|
||||
}
|
||||
}
|
||||
if ($yielded instanceof self) {
|
||||
$yielded->parentCoroutine = $this;
|
||||
}
|
||||
$this->immediate = false;
|
||||
$yielded->onResolve($this->onResolve);
|
||||
} while ($this->immediate);
|
||||
@ -178,14 +165,32 @@ final class Coroutine implements Promise, \ArrayAccess
|
||||
$yielded->onResolve($this->onResolve);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw exception into the generator
|
||||
*
|
||||
* @param \Throwable $reason Exception
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function throw(\Throwable $reason)
|
||||
{
|
||||
if (!isset($reason->yieldedFrames)) {
|
||||
if (method_exists($reason, 'updateTLTrace')) {
|
||||
$reason->updateTLTrace($this->getTrace());
|
||||
} else {
|
||||
$reason->yieldedFrames = $this->getTrace();
|
||||
}
|
||||
}
|
||||
$this->generator->throw($reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Throwable $reason Failure reason.
|
||||
*/
|
||||
public function fail(\Throwable $reason)
|
||||
{
|
||||
//if (isset(\class_uses($reason)[TL\PrettyException::class])) {
|
||||
//$reason->updateTLTrace($this->getTrace());
|
||||
//}
|
||||
$this->resolve(new Failure($reason));
|
||||
}
|
||||
|
||||
@ -246,13 +251,48 @@ final class Coroutine implements Promise, \ArrayAccess
|
||||
return $result->{$name}($arguments);
|
||||
})());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stacktrace from when the generator was started.
|
||||
* Get current stack trace for running coroutine.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTrace(): array
|
||||
{
|
||||
return $this->trace->getTrace();
|
||||
$frames = [];
|
||||
try {
|
||||
$reflector = new ReflectionGenerator($this->generator);
|
||||
$frames = $reflector->getTrace();
|
||||
$frames []= \array_merge(
|
||||
$this->parentCoroutine ? $this->parentCoroutine->getFrame() : [],
|
||||
[
|
||||
'function' => $reflector->getFunction()->getName(),
|
||||
'args' => []
|
||||
]
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
if ($this->parentCoroutine) {
|
||||
$frames = \array_merge($frames, $this->parentCoroutine->getTrace());
|
||||
}
|
||||
return $frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current execution frame
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFrame(): array
|
||||
{
|
||||
try {
|
||||
$reflector = new ReflectionGenerator($this->generator);
|
||||
return [
|
||||
'file' => $reflector->getExecutingFile(),
|
||||
'line' => $reflector->getExecutingLine(),
|
||||
];
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ trait ResponseHandler
|
||||
|
||||
return;
|
||||
}
|
||||
if (\in_array($response['error_message'], ['MSGID_DECREASE_RETRY', 'RPC_CALL_FAIL', 'PERSISTENT_TIMESTAMP_OUTDATED', 'RPC_MCGET_FAIL', 'no workers running', 'No workers running'])) {
|
||||
if (\in_array($response['error_message'], ['MSGID_DECREASE_RETRY', 'HISTORY_GET_FAILED', 'RPC_CALL_FAIL', 'PERSISTENT_TIMESTAMP_OUTDATED', 'RPC_MCGET_FAIL', 'no workers running', 'No workers running'])) {
|
||||
Loop::delay(1 * 1000, [$this, 'methodRecall'], ['message_id' => $request_id, ]);
|
||||
return;
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ResponseHandler module.
|
||||
*
|
||||
* This file is part of MadelineProto.
|
||||
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Affero General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
|
||||
*
|
||||
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
/**
|
||||
* Represents a piece of a coroutine stack trace.
|
||||
*/
|
||||
class Trace
|
||||
{
|
||||
/**
|
||||
* Next piece of the stack trace.
|
||||
*
|
||||
* @var Trace
|
||||
*/
|
||||
private $next;
|
||||
/**
|
||||
* Current stack trace frames.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $frames = [];
|
||||
/**
|
||||
* Create trace.
|
||||
*
|
||||
* @param array $frames Current frames
|
||||
* @param self $next Next trace
|
||||
*/
|
||||
public function __construct(array $frames, self $next = null)
|
||||
{
|
||||
$this->frames = $frames;
|
||||
$this->next = $next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stack trace.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTrace(): array
|
||||
{
|
||||
return \iterator_to_array($this->getTraceGenerator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stack trace.
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
private function getTraceGenerator(): \Generator
|
||||
{
|
||||
foreach ($this->frames as $frame) {
|
||||
yield $frame;
|
||||
}
|
||||
if ($this->next) {
|
||||
yield from $this->next->getTraceGenerator();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user