Optimize session initialization on server start.

This commit is contained in:
Alexander Pankratov 2020-02-06 02:54:22 +03:00
parent 58510aca4a
commit 60e53afcd9

View File

@ -58,72 +58,57 @@ class Client
} }
} }
public function connect($sessionFiles) private static function isInstanceLoggedIn($instance): bool
{ {
//При каждой инициализации настройки обновляются из массива $config return ($instance->API->authorized ?? MTProto::NOT_LOGGED_IN) === MTProto::LOGGED_IN;
echo PHP_EOL . 'Starting MadelineProto...' . PHP_EOL; }
$time = microtime(true);
public function connect($sessionFiles): void
{
Logger::getInstance()->warning(PHP_EOL . 'Starting MadelineProto...' . PHP_EOL);
foreach ($sessionFiles as $file) { foreach ($sessionFiles as $file) {
$session = static::getSessionName($file); $session = static::getSessionName($file);
$this->addSession($session, true); $this->addSession($session);
} }
$this->startSessions();
$time = round(microtime(true) - $time, 3);
$sessionsCount = count($sessionFiles); $sessionsCount = count($sessionFiles);
Logger::getInstance()->warning(
echo
"\nTelegramApiServer ready." "\nTelegramApiServer ready."
. "\nNumber of sessions: {$sessionsCount}." . "\nNumber of sessions: {$sessionsCount}."
. "\nElapsed time: {$time} sec.\n" );
;
} }
public function addSession(string $session, array $settings = []): void public function addSession(string $session, array $settings = []): void
{ {
$settings = (array) Config::getInstance()->get('telegram');
$file = static::getSessionFile($session); $file = static::getSessionFile($session);
$settings = array_replace_recursive((array) Config::getInstance()->get('telegram'), $settings); $settings = array_replace_recursive((array) Config::getInstance()->get('telegram'), $settings);
$instance = new MadelineProto\API($file, $settings); $instance = new MadelineProto\API($file, $settings);
$instance->async(true); $instance->async(true);
$this->instances[$session] = $instance; $this->instances[$session] = $instance;
$isLoggedIn = ($instance->API->authorized ?? MTProto::NOT_LOGGED_IN) === MTProto::LOGGED_IN; Loop::defer(
if($isLoggedIn || $startSession === true) { function() use ($instance) {
$instance->loop(function() use($instance) { if (static::isInstanceLoggedIn($instance)) {
yield $instance->start(); $instance->setEventHandler(EventHandler::class);
}); $this->loop($instance);
}
if ($isLoggedIn) {
$instance->setEventHandler(EventHandler::class);
Loop::defer(function() use($instance) {
$sessionName = self::getSessionName($instance->session);
try {
$instance->loop();
} catch (\Throwable $e) {
Logger::getInstance()->critical($e->getMessage(), [
'session' => $sessionName,
'exception' => [
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile(),
'line' => $e->getLine(),
],
]);
$this->removeSession($sessionName);
} }
}); }
} );
} }
public function removeSession($session) public function removeSession($session): void
{ {
if (empty($this->instances[$session])) { if (empty($this->instances[$session])) {
throw new InvalidArgumentException('Instance not found'); throw new InvalidArgumentException('Instance not found');
} }
$this->instances[$session]->stop(); $this->instances[$session]->stop();
unset($this->instances[$session], EventHandler::$instances[$session]); unset(
$this->instances[$session],
EventHandler::$instances[$session]
);
} }
/** /**
@ -134,14 +119,18 @@ class Client
public function getInstance(?string $session = null): MadelineProto\API public function getInstance(?string $session = null): MadelineProto\API
{ {
if (!$this->instances) { if (!$this->instances) {
throw new RuntimeException('No sessions available. Use combinedApi or restart server with --session option'); throw new RuntimeException(
'No sessions available. Use combinedApi or restart server with --session option'
);
} }
if (!$session) { if (!$session) {
if (count($this->instances) === 1) { if (count($this->instances) === 1) {
$session = (string) array_key_first($this->instances); $session = (string) array_key_first($this->instances);
} else { } else {
throw new InvalidArgumentException('Multiple sessions detected. Specify which session to use. See README for examples.'); throw new InvalidArgumentException(
'Multiple sessions detected. Specify which session to use. See README for examples.'
);
} }
} }
@ -152,4 +141,51 @@ class Client
return $this->instances[$session]; return $this->instances[$session];
} }
private function startSessions(): void
{
Loop::defer(
function() {
foreach ($this->instances as $instance) {
if (!static::isInstanceLoggedIn($instance)) {
$this->loop(
$instance,
static function() use ($instance) {
yield $instance->start();
}
);
}
}
}
);
}
private function loop(MadelineProto\API $instance, callable $callback = null): bool
{
$sessionName = self::getSessionName($instance->session);
try {
if ($callback) {
$instance->loop($callback);
} else {
$instance->loop();
}
} catch (\Throwable $e) {
Logger::getInstance()->critical(
$e->getMessage(),
[
'session' => $sessionName,
'exception' => [
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile(),
'line' => $e->getLine(),
],
]
)
;
$this->removeSession($sessionName);
return false;
}
return true;
}
} }