Merge branch 'new_db_properties' of https://github.com/xtrime-ru/MadelineProto into xtrime-ru-new_db_properties
This commit is contained in:
commit
07248a4803
@ -22,18 +22,6 @@ trait DbPropertiesTrait
|
|||||||
$this->{$property} = yield DbPropertiesFabric::get($dbSettings, $prefix, $type, $property, $this->{$property});
|
$this->{$property} = yield DbPropertiesFabric::get($dbSettings, $prefix, $type, $property, $this->{$property});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$reset && yield $this->usernames->count() === 0) {
|
|
||||||
$this->logger('Filling database cache. This can take few minutes.', Logger::WARNING);
|
|
||||||
$iterator = $this->chats->getIterator();
|
|
||||||
while (yield $iterator->advance()) {
|
|
||||||
[$id, $chat] = $iterator->getCurrent();
|
|
||||||
if (isset($chat['username'])) {
|
|
||||||
$this->usernames[\strtolower($chat['username'])] = $this->getId($chat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->logger('Cache filled.', Logger::WARNING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getSessionId(MTProto $madelineProto): string
|
private static function getSessionId(MTProto $madelineProto): string
|
||||||
|
@ -353,6 +353,13 @@ class MysqlArray implements DbArray
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!empty($params['index'])
|
||||||
|
&& !mb_check_encoding($params['index'], 'UTF-8')
|
||||||
|
) {
|
||||||
|
$params['index'] = mb_convert_encoding($params['index'], 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$request = yield $this->db->execute($query, $params);
|
$request = yield $this->db->execute($query, $params);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
@ -365,6 +365,13 @@ class PostgresArray implements DbArray
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!empty($params['index'])
|
||||||
|
&& !mb_check_encoding($params['index'], 'UTF-8')
|
||||||
|
) {
|
||||||
|
$params['index'] = mb_convert_encoding($params['index'], 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$request = yield $this->db->execute($query, $params);
|
$request = yield $this->db->execute($query, $params);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
@ -272,7 +272,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
/**
|
/**
|
||||||
* Internal peer database.
|
* Internal peer database.
|
||||||
*
|
*
|
||||||
* @var DbArray
|
* @var DbArray|Promise[]
|
||||||
*/
|
*/
|
||||||
public $chats;
|
public $chats;
|
||||||
|
|
||||||
@ -492,7 +492,10 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
*/
|
*/
|
||||||
public function __sleep(): array
|
public function __sleep(): array
|
||||||
{
|
{
|
||||||
if ($this->settings['serialization']['cleanup_before_serialization']) {
|
if (
|
||||||
|
$this->settings['serialization']['cleanup_before_serialization']
|
||||||
|
&& $this->settings['db']['type'] === 'memory'
|
||||||
|
) {
|
||||||
$this->cleanup();
|
$this->cleanup();
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
@ -562,9 +565,9 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
/**
|
/**
|
||||||
* Cleanup memory and session file.
|
* Cleanup memory and session file.
|
||||||
*
|
*
|
||||||
* @return self
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function cleanup(): self
|
public function cleanup(): void
|
||||||
{
|
{
|
||||||
$this->referenceDatabase = new ReferenceDatabase($this);
|
$this->referenceDatabase = new ReferenceDatabase($this);
|
||||||
$callbacks = [$this, $this->referenceDatabase];
|
$callbacks = [$this, $this->referenceDatabase];
|
||||||
@ -572,8 +575,23 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
$callbacks[] = $this->minDatabase;
|
$callbacks[] = $this->minDatabase;
|
||||||
}
|
}
|
||||||
$this->TL->updateCallbacks($callbacks);
|
$this->TL->updateCallbacks($callbacks);
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function fillUsernamesCache(): \Generator
|
||||||
|
{
|
||||||
|
if (yield $this->usernames->count() === 0) {
|
||||||
|
$this->logger('Filling database cache. This can take few minutes.', Logger::WARNING);
|
||||||
|
$iterator = $this->chats->getIterator();
|
||||||
|
while (yield $iterator->advance()) {
|
||||||
|
[$id, $chat] = $iterator->getCurrent();
|
||||||
|
if (isset($chat['username'])) {
|
||||||
|
$this->usernames[\strtolower($chat['username'])] = $this->getId($chat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->logger('Cache filled.', Logger::WARNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger.
|
* Logger.
|
||||||
*
|
*
|
||||||
@ -821,6 +839,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
}
|
}
|
||||||
|
|
||||||
yield from $this->initDb($this);
|
yield from $this->initDb($this);
|
||||||
|
yield from $this->fillUsernamesCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,23 +19,30 @@
|
|||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
|
use Amp\Loop;
|
||||||
|
use Amp\Promise;
|
||||||
|
use danog\MadelineProto\Db\DbArray;
|
||||||
|
use danog\MadelineProto\Db\DbPropertiesTrait;
|
||||||
use danog\MadelineProto\MTProto;
|
use danog\MadelineProto\MTProto;
|
||||||
use danog\MadelineProto\TL\TLCallback;
|
use danog\MadelineProto\TL\TLCallback;
|
||||||
|
use danog\MadelineProto\Tools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages min peers.
|
* Manages min peers.
|
||||||
*/
|
*/
|
||||||
class MinDatabase implements TLCallback
|
class MinDatabase implements TLCallback
|
||||||
{
|
{
|
||||||
|
use DbPropertiesTrait;
|
||||||
|
|
||||||
const SWITCH_CONSTRUCTORS = ['inputChannel', 'inputUser', 'inputPeerUser', 'inputPeerChannel'];
|
const SWITCH_CONSTRUCTORS = ['inputChannel', 'inputUser', 'inputPeerUser', 'inputPeerChannel'];
|
||||||
const CATCH_PEERS = ['message', 'messageService', 'peerUser', 'peerChannel', 'messageEntityMentionName', 'messageFwdHeader', 'messageActionChatCreate', 'messageActionChatAddUser', 'messageActionChatDeleteUser', 'messageActionChatJoinedByLink'];
|
const CATCH_PEERS = ['message', 'messageService', 'peerUser', 'peerChannel', 'messageEntityMentionName', 'messageFwdHeader', 'messageActionChatCreate', 'messageActionChatAddUser', 'messageActionChatDeleteUser', 'messageActionChatJoinedByLink'];
|
||||||
const ORIGINS = ['message', 'messageService'];
|
const ORIGINS = ['message', 'messageService'];
|
||||||
/**
|
/**
|
||||||
* References indexed by location.
|
* References indexed by location.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var DbArray|Promise[]
|
||||||
*/
|
*/
|
||||||
private $db = [];
|
private $db;
|
||||||
/**
|
/**
|
||||||
* Temporary cache during deserialization.
|
* Temporary cache during deserialization.
|
||||||
*
|
*
|
||||||
@ -48,6 +55,16 @@ class MinDatabase implements TLCallback
|
|||||||
* @var \danog\MadelineProto\MTProto
|
* @var \danog\MadelineProto\MTProto
|
||||||
*/
|
*/
|
||||||
private $API;
|
private $API;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of properties stored in database (memory or external).
|
||||||
|
* @see DbPropertiesFabric
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected array $dbProperies = [
|
||||||
|
'db' => 'array',
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct(MTProto $API)
|
public function __construct(MTProto $API)
|
||||||
{
|
{
|
||||||
$this->API = $API;
|
$this->API = $API;
|
||||||
@ -63,11 +80,16 @@ class MinDatabase implements TLCallback
|
|||||||
}
|
}
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
foreach ($this->db as $id => $origin) {
|
Tools::wait($this->initDb($this->API));
|
||||||
|
Loop::defer(function() {
|
||||||
|
$iterator = $this->db->getIterator();
|
||||||
|
while (yield $iterator->advance()) {
|
||||||
|
[$id, $origin] = $iterator->getCurrent();
|
||||||
if (!isset($origin['peer']) || $origin['peer'] === $id) {
|
if (!isset($origin['peer']) || $origin['peer'] === $id) {
|
||||||
unset($this->db[$id]);
|
$this->db->offsetUnset($id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
public function getMethodCallbacks(): array
|
public function getMethodCallbacks(): array
|
||||||
{
|
{
|
||||||
@ -202,7 +224,7 @@ class MinDatabase implements TLCallback
|
|||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
$id = $this->API->getId($object);
|
$id = $this->API->getId($object);
|
||||||
if (isset($this->db[$id])) {
|
if (yield $this->db[$id]) {
|
||||||
$new = \array_merge($object, $this->db[$id]);
|
$new = \array_merge($object, $this->db[$id]);
|
||||||
$new['_'] .= 'FromMessage';
|
$new['_'] .= 'FromMessage';
|
||||||
$new['peer'] = (yield from $this->API->getInfo($new['peer']))['InputPeer'];
|
$new['peer'] = (yield from $this->API->getInfo($new['peer']))['InputPeer'];
|
||||||
@ -215,16 +237,17 @@ class MinDatabase implements TLCallback
|
|||||||
$this->API->logger->logger("Don't have origin info with min peer {$id}, this may fail");
|
$this->API->logger->logger("Don't have origin info with min peer {$id}, this may fail");
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if location info is available for peer.
|
* Check if location info is available for peer.
|
||||||
*
|
*
|
||||||
* @param float|int $id Peer ID
|
* @param float|int $id Peer ID
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean<Promise>
|
||||||
*/
|
*/
|
||||||
public function hasPeer($id): bool
|
public function hasPeer($id): Promise
|
||||||
{
|
{
|
||||||
return isset($this->db[$id]);
|
return $this->db->isset($id);
|
||||||
}
|
}
|
||||||
public function __debugInfo()
|
public function __debugInfo()
|
||||||
{
|
{
|
||||||
|
@ -518,7 +518,7 @@ trait PeerHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yield $this->chats[$id]) {
|
if (yield $this->chats[$id]) {
|
||||||
if (((yield $this->chats[$id])['min'] ?? false) && $this->minDatabase->hasPeer($id) && !isset($this->caching_full_info[$id])) {
|
if (((yield $this->chats[$id])['min'] ?? false) && yield $this->minDatabase->hasPeer($id) && !isset($this->caching_full_info[$id])) {
|
||||||
$this->caching_full_info[$id] = true;
|
$this->caching_full_info[$id] = true;
|
||||||
$this->logger->logger("Only have min peer for {$id} in database, trying to fetch full info");
|
$this->logger->logger("Only have min peer for {$id} in database, trying to fetch full info");
|
||||||
try {
|
try {
|
||||||
|
@ -19,15 +19,21 @@
|
|||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
|
use Amp\Loop;
|
||||||
|
use Amp\Promise;
|
||||||
|
use danog\MadelineProto\Db\DbArray;
|
||||||
|
use danog\MadelineProto\Db\DbPropertiesTrait;
|
||||||
use danog\MadelineProto\Exception;
|
use danog\MadelineProto\Exception;
|
||||||
use danog\MadelineProto\MTProto;
|
use danog\MadelineProto\MTProto;
|
||||||
use danog\MadelineProto\TL\TLCallback;
|
use danog\MadelineProto\TL\TLCallback;
|
||||||
|
use danog\MadelineProto\Tools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages upload and download of files.
|
* Manages upload and download of files.
|
||||||
*/
|
*/
|
||||||
class ReferenceDatabase implements TLCallback
|
class ReferenceDatabase implements TLCallback
|
||||||
{
|
{
|
||||||
|
use DbPropertiesTrait;
|
||||||
|
|
||||||
// Reference from a document
|
// Reference from a document
|
||||||
const DOCUMENT_LOCATION = 0;
|
const DOCUMENT_LOCATION = 0;
|
||||||
@ -65,15 +71,25 @@ class ReferenceDatabase implements TLCallback
|
|||||||
/**
|
/**
|
||||||
* References indexed by location.
|
* References indexed by location.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var DbArray|Promise[]
|
||||||
*/
|
*/
|
||||||
private $db = [];
|
private $db;
|
||||||
private $cache = [];
|
private $cache = [];
|
||||||
private $cacheContexts = [];
|
private $cacheContexts = [];
|
||||||
private $refreshed = [];
|
private $refreshed = [];
|
||||||
private $API;
|
private $API;
|
||||||
private $refresh = false;
|
private $refresh = false;
|
||||||
private $refreshCount = 0;
|
private $refreshCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of properties stored in database (memory or external).
|
||||||
|
* @see DbPropertiesFabric
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected array $dbProperies = [
|
||||||
|
'db' => 'array',
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct(MTProto $API)
|
public function __construct(MTProto $API)
|
||||||
{
|
{
|
||||||
$this->API = $API;
|
$this->API = $API;
|
||||||
@ -89,6 +105,7 @@ class ReferenceDatabase implements TLCallback
|
|||||||
}
|
}
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
|
Tools::wait($this->initDb($this->API));
|
||||||
}
|
}
|
||||||
public function getMethodCallbacks(): array
|
public function getMethodCallbacks(): array
|
||||||
{
|
{
|
||||||
@ -355,11 +372,14 @@ class ReferenceDatabase implements TLCallback
|
|||||||
}
|
}
|
||||||
public function storeReference(string $location, string $reference, int $originType, array $origin)
|
public function storeReference(string $location, string $reference, int $originType, array $origin)
|
||||||
{
|
{
|
||||||
if (!isset($this->db[$location])) {
|
$locationValue = Tools::wait($this->db[$location]);
|
||||||
$this->db[$location] = ['origins' => []];
|
if (!$locationValue) {
|
||||||
|
$locationValue = ['origins' => []];
|
||||||
}
|
}
|
||||||
$this->db[$location]['reference'] = $reference;
|
$locationValue['reference'] = $reference;
|
||||||
$this->db[$location]['origins'][$originType] = $origin;
|
$locationValue['origins'][$originType] = $origin;
|
||||||
|
$this->db[$location] = $locationValue;
|
||||||
|
|
||||||
if ($this->refresh) {
|
if ($this->refresh) {
|
||||||
$this->refreshed[$location] = true;
|
$this->refreshed[$location] = true;
|
||||||
}
|
}
|
||||||
@ -393,11 +413,13 @@ class ReferenceDatabase implements TLCallback
|
|||||||
{
|
{
|
||||||
if (isset($this->refreshed[$location])) {
|
if (isset($this->refreshed[$location])) {
|
||||||
$this->API->logger->logger('Reference already refreshed!', \danog\MadelineProto\Logger::VERBOSE);
|
$this->API->logger->logger('Reference already refreshed!', \danog\MadelineProto\Logger::VERBOSE);
|
||||||
return $this->db[$location]['reference'];
|
return (yield $this->db[$location])['reference'];
|
||||||
}
|
}
|
||||||
\ksort($this->db[$location]['origins']);
|
$locationValue = yield $this->db[$location];
|
||||||
|
\ksort($locationValue['origins']);
|
||||||
|
$this->db[$location] = $locationValue;
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($this->db[$location]['origins'] as $originType => &$origin) {
|
foreach ((yield $this->db[$location]['origins']) as $originType => &$origin) {
|
||||||
$count++;
|
$count++;
|
||||||
$this->API->logger->logger("Try {$count} refreshing file reference with origin type {$originType}", \danog\MadelineProto\Logger::VERBOSE);
|
$this->API->logger->logger("Try {$count} refreshing file reference with origin type {$originType}", \danog\MadelineProto\Logger::VERBOSE);
|
||||||
switch ($originType) {
|
switch ($originType) {
|
||||||
@ -447,7 +469,7 @@ class ReferenceDatabase implements TLCallback
|
|||||||
throw new \danog\MadelineProto\Exception("Unknown origin type {$originType}");
|
throw new \danog\MadelineProto\Exception("Unknown origin type {$originType}");
|
||||||
}
|
}
|
||||||
if (isset($this->refreshed[$location])) {
|
if (isset($this->refreshed[$location])) {
|
||||||
return $this->db[$location]['reference'];
|
return (yield $this->db[$location])['reference'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Exception('Did not refresh reference');
|
throw new Exception('Did not refresh reference');
|
||||||
@ -460,7 +482,7 @@ class ReferenceDatabase implements TLCallback
|
|||||||
public function getReference(int $locationType, array $location)
|
public function getReference(int $locationType, array $location)
|
||||||
{
|
{
|
||||||
$locationString = $this->serializeLocation($locationType, $location);
|
$locationString = $this->serializeLocation($locationType, $location);
|
||||||
if (!isset($this->db[$locationString]['reference'])) {
|
if (!isset((yield $this->db[$locationString])['reference'])) {
|
||||||
if (isset($location['file_reference'])) {
|
if (isset($location['file_reference'])) {
|
||||||
$this->API->logger->logger("Using outdated file reference for location of type {$locationType} object {$location['_']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
$this->API->logger->logger("Using outdated file reference for location of type {$locationType} object {$location['_']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
return $location['file_reference'];
|
return $location['file_reference'];
|
||||||
@ -475,7 +497,7 @@ class ReferenceDatabase implements TLCallback
|
|||||||
if ($this->refresh) {
|
if ($this->refresh) {
|
||||||
return $this->refreshReferenceInternal($locationString);
|
return $this->refreshReferenceInternal($locationString);
|
||||||
}
|
}
|
||||||
return $this->db[$locationString]['reference'];
|
return (yield $this->db[$locationString])['reference'];
|
||||||
}
|
}
|
||||||
private function serializeLocation(int $locationType, array $location)
|
private function serializeLocation(int $locationType, array $location)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user