Upgrade for MysqlArray initialization

This commit is contained in:
Alexander Pankratov 2020-05-17 22:04:32 +03:00
parent 9016a7c0dd
commit fea71efc99
5 changed files with 66 additions and 43 deletions

View File

@ -2,6 +2,7 @@
namespace danog\MadelineProto\Db; namespace danog\MadelineProto\Db;
use Amp\Promise;
use danog\MadelineProto\MTProto; use danog\MadelineProto\MTProto;
class DbPropertiesFabric class DbPropertiesFabric
@ -12,13 +13,13 @@ class DbPropertiesFabric
* @param string $name * @param string $name
* @param $value * @param $value
* *
* @return DbType * @return Promise<DbType>
* *
* @uses \danog\MadelineProto\Db\MemoryArray * @uses \danog\MadelineProto\Db\MemoryArray
* @uses \danog\MadelineProto\Db\SharedMemoryArray * @uses \danog\MadelineProto\Db\SharedMemoryArray
* @uses \danog\MadelineProto\Db\MysqlArray * @uses \danog\MadelineProto\Db\MysqlArray
*/ */
public static function get(MTProto $madelineProto, string $propertyType, string $name, $value = null): DbType public static function get(MTProto $madelineProto, string $propertyType, string $name, $value = null): Promise
{ {
$class = __NAMESPACE__; $class = __NAMESPACE__;
$dbSettings = $madelineProto->settings['db']; $dbSettings = $madelineProto->settings['db'];

View File

@ -2,7 +2,17 @@
namespace danog\MadelineProto\Db; namespace danog\MadelineProto\Db;
use Amp\Promise;
interface DbType interface DbType
{ {
static function getInstance(string $name, $value = null, string $tablePrefix = '', array $settings = []): self; /**
* @param string $name
* @param null $value
* @param string $tablePrefix
* @param array $settings
*
* @return Promise<self>
*/
static function getInstance(string $name, $value = null, string $tablePrefix = '', array $settings = []): Promise;
} }

View File

@ -13,12 +13,14 @@ class MemoryArray extends \ArrayIterator implements DbArray
parent::__construct((array) $array, $flags | self::STD_PROP_LIST); parent::__construct((array) $array, $flags | self::STD_PROP_LIST);
} }
public static function getInstance(string $name, $value = null, string $tablePrefix = '', array $settings = []): DbArray public static function getInstance(string $name, $value = null, string $tablePrefix = '', array $settings = []): Promise
{ {
if ($value instanceof DbArray) { return call(function() use ($value) {
$value = $value->getArrayCopy(); if ($value instanceof DbArray) {
} $value = $value->getArrayCopy();
return new static($value); }
return new static($value);
});
} }
public function offsetExists($offset): Promise public function offsetExists($offset): Promise

View File

@ -40,7 +40,7 @@ class MysqlArray implements DbArray
} }
public static function getInstance(string $name, $value = null, string $tablePrefix = '', array $settings = []): DbType public static function getInstance(string $name, $value = null, string $tablePrefix = '', array $settings = []): Promise
{ {
$instance = new static(); $instance = new static();
@ -49,43 +49,51 @@ class MysqlArray implements DbArray
$instance->db = static::getDbConnection($settings); $instance->db = static::getDbConnection($settings);
$instance->ttl = $settings['cache_ttl'] ?? $instance->ttl; $instance->ttl = $settings['cache_ttl'] ?? $instance->ttl;
Loop::defer(static function() use($value, $instance) { return call(static function() use($instance, $value) {
if ($value instanceof static && $value->table) { yield from static::renameTmpTable($instance, $value);
if (
mb_strpos($value->table, 'tmp') === 0 &&
mb_strpos($instance->table, 'tmp') !== 0
) {
yield from $instance->renameTable($value->table, $instance->table);
} elseif (mb_strpos($instance->table, 'tmp') === 0){
$instance->table = $value->table;
}
}
yield from $instance->prepareTable(); yield from $instance->prepareTable();
Loop::defer(fn() => static::migrateDataToDb($instance, $value));
if (!empty($value) && !$value instanceof static) { return $instance;
Logger::log('Converting database.', Logger::ERROR);
if ($value instanceof DbArray) {
$value = $value->getArrayCopy();
}
$value = (array) $value;
$counter = 0;
$total = count($value);
foreach ((array) $value as $key => $item) {
$counter++;
if ($counter % 100 === 0) {
yield $instance->offsetSet($key, $item);
Logger::log("Converting database. $counter/$total", Logger::WARNING);
} else {
$instance->offsetSet($key, $item);
}
}
Logger::log('Converting database done.', Logger::ERROR);
}
}); });
}
return $instance; private static function renameTmpTable(MysqlArray $instance, ?DbArray $value): \Generator
{
if ($value instanceof static && $value->table) {
if (
mb_strpos($value->table, 'tmp') === 0 &&
mb_strpos($instance->table, 'tmp') !== 0
) {
yield from $instance->renameTable($value->table, $instance->table);
} elseif (mb_strpos($instance->table, 'tmp') === 0) {
$instance->table = $value->table;
}
}
}
private static function migrateDataToDb(MysqlArray $instance, ?DbArray $value): \Generator
{
if (!empty($value) && !$value instanceof static) {
Logger::log('Converting database.', Logger::ERROR);
if ($value instanceof DbArray) {
$value = $value->getArrayCopy();
}
$value = (array) $value;
$counter = 0;
$total = count($value);
foreach ((array) $value as $key => $item) {
$counter++;
if ($counter % 100 === 0) {
yield $instance->offsetSet($key, $item);
Logger::log("Converting database. $counter/$total", Logger::WARNING);
} else {
$instance->offsetSet($key, $item);
}
}
Logger::log('Converting database done.', Logger::ERROR);
}
} }
/** /**
@ -262,6 +270,7 @@ class MysqlArray implements DbArray
*/ */
private function prepareTable() private function prepareTable()
{ {
Logger::log("Creating/checking table {$this->table}", Logger::WARNING);
return yield $this->request(" return yield $this->request("
CREATE TABLE IF NOT EXISTS `{$this->table}` CREATE TABLE IF NOT EXISTS `{$this->table}`
( (
@ -278,6 +287,7 @@ class MysqlArray implements DbArray
private function renameTable(string $from, string $to) private function renameTable(string $from, string $to)
{ {
Logger::log("Renaming table {$from} to {$to}", Logger::WARNING);
yield $this->request(" yield $this->request("
ALTER TABLE `{$from}` RENAME TO `{$to}`; ALTER TABLE `{$from}` RENAME TO `{$to}`;
"); ");

View File

@ -572,7 +572,7 @@ class MTProto extends AsyncConstruct implements TLCallback
if ($reset) { if ($reset) {
unset($this->{$property}); unset($this->{$property});
} else { } else {
$this->{$property} = DbPropertiesFabric::get($this, $type, $property, $this->{$property}); $this->{$property} = yield DbPropertiesFabric::get($this, $type, $property, $this->{$property});
} }
} }