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. */
|
/** @var mixed Promise success value when executing next coroutine step, null at all other times. */
|
||||||
private $value;
|
private $value;
|
||||||
|
|
||||||
/**
|
/** @var ?self Reference to coroutine that started this coroutine */
|
||||||
* Generator trace.
|
private $parentCoroutine;
|
||||||
*
|
|
||||||
* @var Trace
|
|
||||||
*/
|
|
||||||
private $trace;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Generator $generator
|
* @param \Generator $generator
|
||||||
*/
|
*/
|
||||||
public function __construct(\Generator $generator, Trace $trace = null)
|
public function __construct(\Generator $generator)
|
||||||
{
|
{
|
||||||
$this->generator = $generator;
|
$this->generator = $generator;
|
||||||
//$this->trace = $trace ?? new Trace(\debug_backtrace());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$yielded = $this->generator->current();
|
$yielded = $this->generator->current();
|
||||||
@ -92,24 +87,13 @@ final class Coroutine implements Promise, \ArrayAccess
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($yielded instanceof \Generator) {
|
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);
|
$yielded = new self($yielded);
|
||||||
} else {
|
} else {
|
||||||
$yielded = $this->generator->send($yielded);
|
$yielded = $this->generator->send($yielded);
|
||||||
}
|
}
|
||||||
|
if ($yielded instanceof self) {
|
||||||
|
$yielded->parentCoroutine = $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (\Throwable $exception) {
|
} catch (\Throwable $exception) {
|
||||||
$this->fail($exception);
|
$this->fail($exception);
|
||||||
@ -133,7 +117,7 @@ final class Coroutine implements Promise, \ArrayAccess
|
|||||||
do {
|
do {
|
||||||
if ($this->exception) {
|
if ($this->exception) {
|
||||||
// Throw exception at current execution point.
|
// Throw exception at current execution point.
|
||||||
$yielded = $this->generator->throw($this->exception);
|
$yielded = $this->throw($this->exception);
|
||||||
} else {
|
} else {
|
||||||
// Send the new value and execute to next yield statement.
|
// Send the new value and execute to next yield statement.
|
||||||
$yielded = $this->generator->send($this->value);
|
$yielded = $this->generator->send($this->value);
|
||||||
@ -163,6 +147,9 @@ final class Coroutine implements Promise, \ArrayAccess
|
|||||||
$yielded = $this->generator->send($yielded);
|
$yielded = $this->generator->send($yielded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($yielded instanceof self) {
|
||||||
|
$yielded->parentCoroutine = $this;
|
||||||
|
}
|
||||||
$this->immediate = false;
|
$this->immediate = false;
|
||||||
$yielded->onResolve($this->onResolve);
|
$yielded->onResolve($this->onResolve);
|
||||||
} while ($this->immediate);
|
} while ($this->immediate);
|
||||||
@ -178,14 +165,32 @@ final class Coroutine implements Promise, \ArrayAccess
|
|||||||
$yielded->onResolve($this->onResolve);
|
$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.
|
* @param \Throwable $reason Failure reason.
|
||||||
*/
|
*/
|
||||||
public function fail(\Throwable $reason)
|
public function fail(\Throwable $reason)
|
||||||
{
|
{
|
||||||
//if (isset(\class_uses($reason)[TL\PrettyException::class])) {
|
|
||||||
//$reason->updateTLTrace($this->getTrace());
|
|
||||||
//}
|
|
||||||
$this->resolve(new Failure($reason));
|
$this->resolve(new Failure($reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,13 +251,48 @@ final class Coroutine implements Promise, \ArrayAccess
|
|||||||
return $result->{$name}($arguments);
|
return $result->{$name}($arguments);
|
||||||
})());
|
})());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get stacktrace from when the generator was started.
|
* Get current stack trace for running coroutine.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getTrace(): 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;
|
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, ]);
|
Loop::delay(1 * 1000, [$this, 'methodRecall'], ['message_id' => $request_id, ]);
|
||||||
return;
|
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