Store main session in database
This commit is contained in:
parent
4123941df3
commit
50ee77c229
@ -20,6 +20,7 @@
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
use Amp\Ipc\Sync\ChannelledSocket;
|
||||
use Amp\Loop;
|
||||
use danog\MadelineProto\Ipc\Client;
|
||||
use danog\MadelineProto\Ipc\Server;
|
||||
use danog\MadelineProto\Settings\Logger as SettingsLogger;
|
||||
@ -159,6 +160,7 @@ class API extends InternalDoc
|
||||
$this->APIFactory();
|
||||
$this->logger->logger(Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnect to full instance.
|
||||
*
|
||||
@ -276,7 +278,7 @@ class API extends InternalDoc
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->methods = self::getInternalMethodList($this->API);
|
||||
$this->methods = self::getInternalMethodList($this->API, MTProto::class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,10 @@ final class APIWrapper
|
||||
yield from $this->API->initAsynchronously();
|
||||
}
|
||||
|
||||
yield from $this->session->serialize($this, $this->session->getSessionPath());
|
||||
yield from $this->session->serialize(
|
||||
yield from $this->API->serializeSession($this),
|
||||
$this->session->getSessionPath()
|
||||
);
|
||||
|
||||
if ($this->API) {
|
||||
yield from $this->session->storeLightState($this->API);
|
||||
|
@ -200,8 +200,8 @@ abstract class AbstractAPIFactory extends AsyncConstruct
|
||||
/**
|
||||
* Get fully resolved method list for object, including snake_case and camelCase variants.
|
||||
*
|
||||
* @param API|MTProto $value Value
|
||||
* @param string $class Custom class name
|
||||
* @param API|MTProto|Client $value Value
|
||||
* @param string $class Custom class name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -27,7 +27,10 @@ class DbPropertiesFactory
|
||||
*/
|
||||
public static function get(DatabaseAbstract $dbSettings, string $namePrefix, string $propertyType, string $name, $value = null): Promise
|
||||
{
|
||||
$class = __NAMESPACE__;
|
||||
$propertyType = \strtolower($propertyType);
|
||||
$class = $propertyType === 'arraynullcache' && !$dbSettings instanceof Memory
|
||||
? __NAMESPACE__.'\\NullCache'
|
||||
: __NAMESPACE__ ;
|
||||
|
||||
switch (true) {
|
||||
case $dbSettings instanceof Memory:
|
||||
@ -49,6 +52,7 @@ class DbPropertiesFactory
|
||||
|
||||
/** @var DbType $class */
|
||||
switch (\strtolower($propertyType)) {
|
||||
case 'arraynullcache':
|
||||
case 'array':
|
||||
$class .= 'Array';
|
||||
break;
|
||||
|
10
src/danog/MadelineProto/Db/NullCache/MysqlArray.php
Normal file
10
src/danog/MadelineProto/Db/NullCache/MysqlArray.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace danog\MadelineProto\Db\NullCache;
|
||||
|
||||
use danog\MadelineProto\Settings\Database\Mysql;
|
||||
|
||||
class MysqlArray extends Mysql
|
||||
{
|
||||
use NullCacheTrait;
|
||||
}
|
36
src/danog/MadelineProto/Db/NullCache/NullCacheTrait.php
Normal file
36
src/danog/MadelineProto/Db/NullCache/NullCacheTrait.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace danog\MadelineProto\Db\NullCache;
|
||||
|
||||
trait NullCacheTrait
|
||||
{
|
||||
protected function getCache(string $key, $default = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Save item in cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param $value
|
||||
*/
|
||||
protected function setCache(string $key, $value): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove key from cache.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
protected function unsetCache(string $key): void
|
||||
{
|
||||
}
|
||||
|
||||
protected function startCacheCleanupLoop(): void
|
||||
{
|
||||
}
|
||||
protected function stopCacheCleanupLoop(): void
|
||||
{
|
||||
}
|
||||
}
|
10
src/danog/MadelineProto/Db/NullCache/PostgresArray.php
Normal file
10
src/danog/MadelineProto/Db/NullCache/PostgresArray.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace danog\MadelineProto\Db\NullCache;
|
||||
|
||||
use danog\MadelineProto\Settings\Database\Postgres;
|
||||
|
||||
class PostgresArray extends Postgres
|
||||
{
|
||||
use NullCacheTrait;
|
||||
}
|
10
src/danog/MadelineProto/Db/NullCache/RedisArray.php
Normal file
10
src/danog/MadelineProto/Db/NullCache/RedisArray.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace danog\MadelineProto\Db\NullCache;
|
||||
|
||||
use danog\MadelineProto\Db\RedisArray as DbRedisArray;
|
||||
|
||||
class RedisArray extends DbRedisArray
|
||||
{
|
||||
use NullCacheTrait;
|
||||
}
|
@ -5404,6 +5404,15 @@ class InternalDoc extends APIFactory
|
||||
{
|
||||
return \danog\MadelineProto\Tools::isArrayOrAlike($var);
|
||||
}
|
||||
/**
|
||||
* Whether we're an IPC client instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isIpc(): bool
|
||||
{
|
||||
return $this->API->isIpc();
|
||||
}
|
||||
/**
|
||||
* Check whether provided bot API ID is a channel.
|
||||
*
|
||||
|
@ -159,6 +159,24 @@ class Client
|
||||
$this->run = false;
|
||||
return $this->server->send(Server::SHUTDOWN);
|
||||
}
|
||||
/**
|
||||
* Restart IPC server instance.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function restartIpcServer(): Promise
|
||||
{
|
||||
return $this->server->send(Server::SHUTDOWN);
|
||||
}
|
||||
/**
|
||||
* Whether we're an IPC client instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isIpc(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Call function.
|
||||
*
|
||||
|
@ -177,6 +177,7 @@ class Server extends SignalLoop
|
||||
$result = $this->API->{$payload[0]}(...$payload[1]);
|
||||
$result = $result instanceof \Generator ? yield from $result : yield $result;
|
||||
} catch (\Throwable $e) {
|
||||
$this->API->logger("Got error while calling IPC method: $e", Logger::ERROR);
|
||||
$result = new ExitFailure($e);
|
||||
}
|
||||
try {
|
||||
|
@ -24,11 +24,13 @@ use Amp\File\StatCache;
|
||||
use Amp\Http\Client\HttpClient;
|
||||
use Amp\Loop;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
use Closure;
|
||||
use danog\MadelineProto\Async\AsyncConstruct;
|
||||
use danog\MadelineProto\Db\DbArray;
|
||||
use danog\MadelineProto\Db\DbPropertiesFactory;
|
||||
use danog\MadelineProto\Db\DbPropertiesTrait;
|
||||
use danog\MadelineProto\Db\MemoryArray;
|
||||
use danog\MadelineProto\Ipc\Server;
|
||||
use danog\MadelineProto\Loop\Generic\PeriodicLoopInternal;
|
||||
use danog\MadelineProto\Loop\Update\FeedLoop;
|
||||
@ -468,6 +470,13 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* Nullcache array for storing main session file to DB.
|
||||
*
|
||||
* @var DbArray|Promise[]
|
||||
*/
|
||||
public $session;
|
||||
|
||||
/**
|
||||
* List of properties stored in database (memory or external).
|
||||
* @see DbPropertiesFactory
|
||||
@ -478,8 +487,23 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
'full_chats' => 'array',
|
||||
'channel_participants' => 'array',
|
||||
'usernames' => 'array',
|
||||
'session' => 'arrayNullCache'
|
||||
];
|
||||
|
||||
/**
|
||||
* Serialize session, returning object to serialize to db.
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
public function serializeSession(object $data): \Generator
|
||||
{
|
||||
if ($this->session instanceof MemoryArray) {
|
||||
return $data;
|
||||
}
|
||||
yield $this->session['data'] = \serialize($data);
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor function.
|
||||
*
|
||||
@ -1130,6 +1154,24 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
$this->unreference();
|
||||
$this->logger("Successfully destroyed MadelineProto");
|
||||
}
|
||||
/**
|
||||
* Restart IPC server instance.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function restartIpcServer(): Promise
|
||||
{
|
||||
return new Success(); // Can only be called from client
|
||||
}
|
||||
/**
|
||||
* Whether we're an IPC client instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isIpc(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Parse, update and store settings.
|
||||
*
|
||||
@ -1166,8 +1208,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
$this->setupLogger();
|
||||
|
||||
if ($reinit) {
|
||||
$this->__construct();
|
||||
yield from $this->initAsynchronously();
|
||||
yield from $this->__construct_async($this->settings);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -22,6 +22,8 @@ namespace danog\MadelineProto;
|
||||
use Amp\Deferred;
|
||||
use Amp\Loop;
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\Db\DbArray;
|
||||
use danog\MadelineProto\Db\DriverArray;
|
||||
use danog\MadelineProto\Ipc\Server;
|
||||
use danog\MadelineProto\MTProtoSession\Session;
|
||||
|
||||
@ -191,6 +193,10 @@ abstract class Serialization
|
||||
|
||||
if ($isNew) {
|
||||
$unserialized = yield from $session->unserialize();
|
||||
if ($unserialized instanceof DriverArray) {
|
||||
yield from $unserialized->initConnection($unserialized->dbSettings);
|
||||
$unserialized = \unserialize(yield $unserialized['data']);
|
||||
}
|
||||
} else {
|
||||
$unserialized = yield from self::legacyUnserialize($session->getLegacySessionPath());
|
||||
}
|
||||
|
@ -177,6 +177,12 @@ class Settings extends SettingsAbstract
|
||||
$this->serialization->merge($settings);
|
||||
} elseif ($settings instanceof TLSchema) {
|
||||
$this->schema->merge($settings);
|
||||
} elseif ($settings instanceof DatabaseAbstract) {
|
||||
if (!$this->db instanceof $settings) {
|
||||
$this->db = $settings;
|
||||
} else {
|
||||
$this->db->merge($settings);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user