mirror of
https://github.com/danog/AsyncOrm.git
synced 2024-11-30 04:39:45 +01:00
Cleanup
This commit is contained in:
parent
4578655304
commit
53c536bf9e
@ -22,6 +22,7 @@ use Attribute;
|
|||||||
use danog\AsyncOrm\KeyType;
|
use danog\AsyncOrm\KeyType;
|
||||||
use danog\AsyncOrm\ValueType;
|
use danog\AsyncOrm\ValueType;
|
||||||
|
|
||||||
|
/** @api */
|
||||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||||
final class OrmMappedArray
|
final class OrmMappedArray
|
||||||
{
|
{
|
||||||
|
@ -30,9 +30,16 @@ use Traversable;
|
|||||||
* @implements ArrayAccess<TKey, TValue>
|
* @implements ArrayAccess<TKey, TValue>
|
||||||
* @implements Traversable<TKey, TValue>
|
* @implements Traversable<TKey, TValue>
|
||||||
* @implements IteratorAggregate<TKey, TValue>
|
* @implements IteratorAggregate<TKey, TValue>
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
abstract class DbArray implements Countable, ArrayAccess, Traversable, IteratorAggregate
|
abstract class DbArray implements Countable, ArrayAccess, Traversable, IteratorAggregate
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Check if element exists.
|
||||||
|
*
|
||||||
|
* @param TKey $key
|
||||||
|
*/
|
||||||
final public function isset(string|int $key): bool
|
final public function isset(string|int $key): bool
|
||||||
{
|
{
|
||||||
return $this->get($key) !== null;
|
return $this->get($key) !== null;
|
||||||
@ -43,19 +50,19 @@ abstract class DbArray implements Countable, ArrayAccess, Traversable, IteratorA
|
|||||||
return $this->get($offset);
|
return $this->get($offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
final public function offsetExists(mixed $index): bool
|
final public function offsetExists(mixed $offset): bool
|
||||||
{
|
{
|
||||||
return $this->isset($index);
|
return $this->isset($offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
final public function offsetSet(mixed $index, mixed $value): void
|
final public function offsetSet(mixed $offset, mixed $value): void
|
||||||
{
|
{
|
||||||
$this->set($index, $value);
|
$this->set($offset, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
final public function offsetUnset(mixed $index): void
|
final public function offsetUnset(mixed $offset): void
|
||||||
{
|
{
|
||||||
$this->unset($index);
|
$this->unset($offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getArrayCopy(): array
|
public function getArrayCopy(): array
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
namespace danog\AsyncOrm;
|
namespace danog\AsyncOrm;
|
||||||
|
|
||||||
use danog\AsyncOrm\Annotations\OrmMappedArray;
|
use danog\AsyncOrm\Annotations\OrmMappedArray;
|
||||||
|
use danog\AsyncOrm\Internal\Containers\ObjectContainer;
|
||||||
use danog\AsyncOrm\Internal\Driver\CachedArray;
|
use danog\AsyncOrm\Internal\Driver\CachedArray;
|
||||||
|
use danog\AsyncOrm\Internal\Driver\ObjectArray;
|
||||||
use danog\AsyncOrm\Settings\DriverSettings;
|
use danog\AsyncOrm\Settings\DriverSettings;
|
||||||
use danog\AsyncOrm\Settings\Mysql;
|
use danog\AsyncOrm\Settings\Mysql;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
@ -27,11 +29,10 @@ use ReflectionClass;
|
|||||||
use function Amp\async;
|
use function Amp\async;
|
||||||
use function Amp\Future\await;
|
use function Amp\Future\await;
|
||||||
|
|
||||||
|
/** @api */
|
||||||
abstract class DbObject
|
abstract class DbObject
|
||||||
{
|
{
|
||||||
/** @var list<CachedArray> */
|
private ObjectContainer $mapper;
|
||||||
private array $properties;
|
|
||||||
private DbArray $mapper;
|
|
||||||
private string|int $key;
|
private string|int $key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,55 +40,10 @@ abstract class DbObject
|
|||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
final public function initDb(DbArray $mapper, string|int $key, FieldConfig $config): void
|
final public function initDb(ObjectContainer $mapper, string|int $key, FieldConfig $config): void
|
||||||
{
|
{
|
||||||
$this->mapper = $mapper;
|
$this->mapper = $mapper;
|
||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
$promises = [];
|
|
||||||
foreach ((new ReflectionClass(static::class))->getProperties() as $property) {
|
|
||||||
$attr = $property->getAttributes(OrmMappedArray::class);
|
|
||||||
if (!$attr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$attr = $attr[0]->newInstance();
|
|
||||||
|
|
||||||
$settings = $config->settings;
|
|
||||||
if ($settings instanceof DriverSettings) {
|
|
||||||
$ttl = $attr->cacheTtl ?? $settings->cacheTtl;
|
|
||||||
if ($ttl !== $settings->cacheTtl) {
|
|
||||||
$settings = new $settings(\array_merge(
|
|
||||||
(array) $settings,
|
|
||||||
['cacheTtl' => $ttl]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if ($settings instanceof Mysql) {
|
|
||||||
$optimize = $attr->optimizeIfWastedGtMb ?? $settings->optimizeIfWastedGtMb;
|
|
||||||
|
|
||||||
if ($optimize !== $settings->optimizeIfWastedGtMb) {
|
|
||||||
$settings = new $settings(\array_merge(
|
|
||||||
(array) $settings,
|
|
||||||
['optimizeIfWastedGtMb' => $optimize]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = new FieldConfig(
|
|
||||||
$config->table.'_'.($attr->tablePostfix ?? $property->getName()),
|
|
||||||
$settings,
|
|
||||||
$attr->keyType,
|
|
||||||
$attr->valueType,
|
|
||||||
);
|
|
||||||
|
|
||||||
$promises[] = async(function () use ($config, $property) {
|
|
||||||
$v = $config->build($property->getValue());
|
|
||||||
$property->setValue($v);
|
|
||||||
if ($v instanceof CachedArray) {
|
|
||||||
$this->properties []= $v;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await($promises);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,10 +51,21 @@ abstract class DbObject
|
|||||||
*/
|
*/
|
||||||
public function save(): void
|
public function save(): void
|
||||||
{
|
{
|
||||||
$promises = [async($this->mapper->set(...), $this->key, $this)];
|
$this->onBeforeSave();
|
||||||
foreach ($this->properties as $v) {
|
$this->mapper->inner->set($this->key, $this);
|
||||||
$promises []= async($v->flushCache(...));
|
$this->onAfterSave();
|
||||||
}
|
}
|
||||||
await($promises);
|
|
||||||
|
/**
|
||||||
|
* Method invoked before saving the object.
|
||||||
|
*/
|
||||||
|
protected function onBeforeSave(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Method invoked after saving the object.
|
||||||
|
*/
|
||||||
|
protected function onAfterSave(): void {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ use function Amp\Future\await;
|
|||||||
* @consistent-constructor
|
* @consistent-constructor
|
||||||
*
|
*
|
||||||
* @extends DbArray<TKey, TValue>
|
* @extends DbArray<TKey, TValue>
|
||||||
|
*
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
abstract class DriverArray extends DbArray
|
abstract class DriverArray extends DbArray
|
||||||
{
|
{
|
||||||
@ -44,7 +46,8 @@ abstract class DriverArray extends DbArray
|
|||||||
|
|
||||||
public static function getInstance(FieldConfig $config, DbArray|null $previous): DbArray
|
public static function getInstance(FieldConfig $config, DbArray|null $previous): DbArray
|
||||||
{
|
{
|
||||||
if ($previous::class === static::class
|
if ($previous !== null
|
||||||
|
&& $previous::class === static::class
|
||||||
&& $previous->config == $config
|
&& $previous->config == $config
|
||||||
) {
|
) {
|
||||||
return $previous;
|
return $previous;
|
||||||
|
@ -28,7 +28,8 @@ use danog\AsyncOrm\Settings\Database\Memory;
|
|||||||
*
|
*
|
||||||
* @template TKey as array-key
|
* @template TKey as array-key
|
||||||
* @template TValue
|
* @template TValue
|
||||||
* @DbArray DbArray<TKey, TValue>
|
* @extends DbArray<TKey, TValue>
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
final class MemoryArray extends DbArray
|
final class MemoryArray extends DbArray
|
||||||
{
|
{
|
||||||
@ -37,7 +38,7 @@ final class MemoryArray extends DbArray
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getInstance(FieldConfig $settings, DbArray|null $previous): DbArray
|
public static function getInstance(FieldConfig $config, DbArray|null $previous): DbArray
|
||||||
{
|
{
|
||||||
if ($previous instanceof self) {
|
if ($previous instanceof self) {
|
||||||
return $previous;
|
return $previous;
|
||||||
|
@ -29,6 +29,7 @@ use danog\AsyncOrm\Serializer;
|
|||||||
* @template TKey as array-key
|
* @template TKey as array-key
|
||||||
* @template TValue
|
* @template TValue
|
||||||
* @extends DriverArray<TKey, TValue>
|
* @extends DriverArray<TKey, TValue>
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
abstract class SqlArray extends DriverArray
|
abstract class SqlArray extends DriverArray
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace danog\AsyncOrm;
|
namespace danog\AsyncOrm;
|
||||||
|
|
||||||
use danog\AsyncOrm\Internal\Driver\CachedArray;
|
use danog\AsyncOrm\Internal\Driver\CachedArray;
|
||||||
|
use danog\AsyncOrm\Internal\Driver\ObjectArray;
|
||||||
use danog\AsyncOrm\Settings\DriverSettings;
|
use danog\AsyncOrm\Settings\DriverSettings;
|
||||||
use danog\AsyncOrm\Settings\Memory;
|
use danog\AsyncOrm\Settings\Memory;
|
||||||
|
|
||||||
@ -40,9 +41,13 @@ final readonly class FieldConfig
|
|||||||
|| (
|
|| (
|
||||||
$this->settings instanceof DriverSettings
|
$this->settings instanceof DriverSettings
|
||||||
&& $this->settings->cacheTtl === 0
|
&& $this->settings->cacheTtl === 0
|
||||||
)) {
|
)
|
||||||
|
) {
|
||||||
return $this->settings->getDriverClass()::getInstance($this, $previous);
|
return $this->settings->getDriverClass()::getInstance($this, $previous);
|
||||||
}
|
}
|
||||||
|
if ($this->valueType === ValueType::OBJECT) {
|
||||||
|
return ObjectArray::getInstance($this, $previous);
|
||||||
|
}
|
||||||
|
|
||||||
return CachedArray::getInstance($this, $previous);
|
return CachedArray::getInstance($this, $previous);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ final class CacheContainer
|
|||||||
public function startCacheCleanupLoop(int $cacheTtl): void
|
public function startCacheCleanupLoop(int $cacheTtl): void
|
||||||
{
|
{
|
||||||
$this->cacheTtl = $cacheTtl;
|
$this->cacheTtl = $cacheTtl;
|
||||||
if ($this->cacheCleanupId) {
|
if ($this->cacheCleanupId !== null) {
|
||||||
EventLoop::cancel($this->cacheCleanupId);
|
EventLoop::cancel($this->cacheCleanupId);
|
||||||
}
|
}
|
||||||
$this->cacheCleanupId = EventLoop::repeat(
|
$this->cacheCleanupId = EventLoop::repeat(
|
||||||
@ -71,7 +71,7 @@ final class CacheContainer
|
|||||||
}
|
}
|
||||||
public function stopCacheCleanupLoop(): void
|
public function stopCacheCleanupLoop(): void
|
||||||
{
|
{
|
||||||
if ($this->cacheCleanupId) {
|
if ($this->cacheCleanupId !== null) {
|
||||||
EventLoop::cancel($this->cacheCleanupId);
|
EventLoop::cancel($this->cacheCleanupId);
|
||||||
$this->cacheCleanupId = null;
|
$this->cacheCleanupId = null;
|
||||||
}
|
}
|
||||||
@ -87,6 +87,7 @@ final class CacheContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->inner->offsetGet($index);
|
$result = $this->inner->offsetGet($index);
|
||||||
|
/** @psalm-suppress ParadoxicalCondition Concurrency */
|
||||||
if (isset($this->ttl[$index])) {
|
if (isset($this->ttl[$index])) {
|
||||||
if ($this->ttl[$index] !== true) {
|
if ($this->ttl[$index] !== true) {
|
||||||
$this->ttl[$index] = \time() + $this->cacheTtl;
|
$this->ttl[$index] = \time() + $this->cacheTtl;
|
||||||
|
@ -22,6 +22,7 @@ use Amp\Sync\LocalMutex;
|
|||||||
use danog\AsyncOrm\DbArray;
|
use danog\AsyncOrm\DbArray;
|
||||||
use danog\AsyncOrm\DbObject;
|
use danog\AsyncOrm\DbObject;
|
||||||
use danog\AsyncOrm\FieldConfig;
|
use danog\AsyncOrm\FieldConfig;
|
||||||
|
use danog\AsyncOrm\Internal\Driver\ObjectArray;
|
||||||
use Revolt\EventLoop;
|
use Revolt\EventLoop;
|
||||||
use Traversable;
|
use Traversable;
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ final class ObjectContainer
|
|||||||
public function startCacheCleanupLoop(int $cacheTtl): void
|
public function startCacheCleanupLoop(int $cacheTtl): void
|
||||||
{
|
{
|
||||||
$this->cacheTtl = $cacheTtl;
|
$this->cacheTtl = $cacheTtl;
|
||||||
if ($this->cacheCleanupId) {
|
if ($this->cacheCleanupId !== null) {
|
||||||
EventLoop::cancel($this->cacheCleanupId);
|
EventLoop::cancel($this->cacheCleanupId);
|
||||||
}
|
}
|
||||||
$this->cacheCleanupId = EventLoop::repeat(
|
$this->cacheCleanupId = EventLoop::repeat(
|
||||||
@ -71,7 +72,7 @@ final class ObjectContainer
|
|||||||
}
|
}
|
||||||
public function stopCacheCleanupLoop(): void
|
public function stopCacheCleanupLoop(): void
|
||||||
{
|
{
|
||||||
if ($this->cacheCleanupId) {
|
if ($this->cacheCleanupId !== null) {
|
||||||
EventLoop::cancel($this->cacheCleanupId);
|
EventLoop::cancel($this->cacheCleanupId);
|
||||||
$this->cacheCleanupId = null;
|
$this->cacheCleanupId = null;
|
||||||
}
|
}
|
||||||
@ -84,7 +85,7 @@ final class ObjectContainer
|
|||||||
$ref = $obj->reference->get();
|
$ref = $obj->reference->get();
|
||||||
if ($ref !== null) {
|
if ($ref !== null) {
|
||||||
$obj->ttl = \time() + $this->cacheTtl;
|
$obj->ttl = \time() + $this->cacheTtl;
|
||||||
return $obj;
|
return $ref;
|
||||||
}
|
}
|
||||||
unset($this->cache[$index]);
|
unset($this->cache[$index]);
|
||||||
}
|
}
|
||||||
@ -95,7 +96,7 @@ final class ObjectContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
\assert($result instanceof DbObject);
|
\assert($result instanceof DbObject);
|
||||||
$result->initDb($this->inner, $index, $this->config);
|
$result->initDb($this, $index, $this->config);
|
||||||
|
|
||||||
$this->cache[$index] = new ObjectReference($result, \time() + $this->cacheTtl);
|
$this->cache[$index] = new ObjectReference($result, \time() + $this->cacheTtl);
|
||||||
|
|
||||||
@ -107,9 +108,9 @@ final class ObjectContainer
|
|||||||
if (isset($this->cache[$key]) && $this->cache[$key]->reference->get() === $value) {
|
if (isset($this->cache[$key]) && $this->cache[$key]->reference->get() === $value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$value->initDb($this->inner, $key, $this->config);
|
$value->initDb($this, $key, $this->config);
|
||||||
$this->cache[$key] = new ObjectReference($value, \time() + $this->cacheTtl);
|
$this->cache[$key] = new ObjectReference($value, \time() + $this->cacheTtl);
|
||||||
$this->inner->set($key, $value);
|
$value->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unset(string|int $key): void
|
public function unset(string|int $key): void
|
||||||
@ -122,6 +123,7 @@ final class ObjectContainer
|
|||||||
{
|
{
|
||||||
$this->flushCache();
|
$this->flushCache();
|
||||||
foreach ($this->inner->getIterator() as $key => $value) {
|
foreach ($this->inner->getIterator() as $key => $value) {
|
||||||
|
assert($value instanceof DbObject);
|
||||||
if (isset($this->cache[$key])) {
|
if (isset($this->cache[$key])) {
|
||||||
$obj = $this->cache[$key];
|
$obj = $this->cache[$key];
|
||||||
$ref = $obj->reference->get();
|
$ref = $obj->reference->get();
|
||||||
@ -131,7 +133,7 @@ final class ObjectContainer
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$value->initDb($this->inner, $key, $this->config);
|
$value->initDb($this, $key, $this->config);
|
||||||
$this->cache[$key] = new ObjectReference($value, \time() + $this->cacheTtl);
|
$this->cache[$key] = new ObjectReference($value, \time() + $this->cacheTtl);
|
||||||
yield $value;
|
yield $value;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ final class CachedArray extends DbArray
|
|||||||
$previous->cache->flushCache();
|
$previous->cache->flushCache();
|
||||||
return $previous->cache->inner;
|
return $previous->cache->inner;
|
||||||
}
|
}
|
||||||
$previous->cache->startCacheCleanupLoop($config->cacheTtl);
|
$previous->cache->startCacheCleanupLoop($config->settings->cacheTtl);
|
||||||
return $previous;
|
return $previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,9 +84,9 @@ final class CachedArray extends DbArray
|
|||||||
$this->cache->clear();
|
$this->cache->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(mixed $index): mixed
|
public function get(mixed $key): mixed
|
||||||
{
|
{
|
||||||
return $this->cache->get($index);
|
return $this->cache->get($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set(string|int $key, mixed $value): void
|
public function set(string|int $key, mixed $value): void
|
||||||
|
@ -128,12 +128,12 @@ final class MysqlArray extends SqlArray
|
|||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
$keyType = match ($config->annotation->keyType) {
|
$keyType = match ($config->keyType) {
|
||||||
KeyType::STRING_OR_INT => "VARCHAR(255)",
|
KeyType::STRING_OR_INT => "VARCHAR(255)",
|
||||||
KeyType::STRING => "VARCHAR(255)",
|
KeyType::STRING => "VARCHAR(255)",
|
||||||
KeyType::INT => "BIGINT",
|
KeyType::INT => "BIGINT",
|
||||||
};
|
};
|
||||||
$valueType = match ($config->annotation->valueType) {
|
$valueType = match ($config->valueType) {
|
||||||
ValueType::INT => "BIGINT",
|
ValueType::INT => "BIGINT",
|
||||||
ValueType::STRING => "VARCHAR(255)",
|
ValueType::STRING => "VARCHAR(255)",
|
||||||
default => "MEDIUMBLOB",
|
default => "MEDIUMBLOB",
|
||||||
@ -143,7 +143,7 @@ final class MysqlArray extends SqlArray
|
|||||||
CREATE TABLE IF NOT EXISTS `{$config->table}`
|
CREATE TABLE IF NOT EXISTS `{$config->table}`
|
||||||
(
|
(
|
||||||
`key` $keyType PRIMARY KEY NOT NULL,
|
`key` $keyType PRIMARY KEY NOT NULL,
|
||||||
`value` $valueType NOT NULL,
|
`value` $valueType NOT NULL
|
||||||
)
|
)
|
||||||
ENGINE = InnoDB
|
ENGINE = InnoDB
|
||||||
CHARACTER SET 'utf8mb4'
|
CHARACTER SET 'utf8mb4'
|
||||||
@ -163,6 +163,7 @@ final class MysqlArray extends SqlArray
|
|||||||
$expected = $valueType;
|
$expected = $valueType;
|
||||||
} else {
|
} else {
|
||||||
$this->db->query("ALTER TABLE `{$config->table}` DROP `$key`");
|
$this->db->query("ALTER TABLE `{$config->table}` DROP `$key`");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if ($expected !== $type || $null !== 'NO') {
|
if ($expected !== $type || $null !== 'NO') {
|
||||||
$this->db->query("ALTER TABLE `{$config->table}` MODIFY `$key` $expected NOT NULL");
|
$this->db->query("ALTER TABLE `{$config->table}` MODIFY `$key` $expected NOT NULL");
|
||||||
|
@ -56,7 +56,7 @@ final class ObjectArray extends DbArray
|
|||||||
$previous->cache->flushCache();
|
$previous->cache->flushCache();
|
||||||
return $previous->cache->inner;
|
return $previous->cache->inner;
|
||||||
}
|
}
|
||||||
$previous->cache->startCacheCleanupLoop($config->cacheTtl);
|
$previous->cache->startCacheCleanupLoop($config->settings->cacheTtl);
|
||||||
return $previous;
|
return $previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +80,9 @@ final class ObjectArray extends DbArray
|
|||||||
$this->cache->clear();
|
$this->cache->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(mixed $index): mixed
|
public function get(mixed $key): mixed
|
||||||
{
|
{
|
||||||
return $this->cache->get($index);
|
return $this->cache->get($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set(string|int $key, mixed $value): void
|
public function set(string|int $key, mixed $value): void
|
||||||
|
@ -70,7 +70,7 @@ class PostgresArray extends SqlArray
|
|||||||
}
|
}
|
||||||
$connection->close();
|
$connection->close();
|
||||||
|
|
||||||
self::$connections[$dbKey] = new PostgresConnectionPool($settings->config, $settings->maxConnections, $settings->idleTimeoutgetIdleTimeout());
|
self::$connections[$dbKey] = new PostgresConnectionPool($settings->config, $settings->maxConnections, $settings->idleTimeout);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
EventLoop::queue($lock->release(...));
|
EventLoop::queue($lock->release(...));
|
||||||
@ -78,17 +78,17 @@ class PostgresArray extends SqlArray
|
|||||||
|
|
||||||
$connection = self::$connections[$dbKey];
|
$connection = self::$connections[$dbKey];
|
||||||
|
|
||||||
$keyType = match ($config->annotation->keyType) {
|
$keyType = match ($config->keyType) {
|
||||||
KeyType::STRING_OR_INT => "VARCHAR(255)",
|
KeyType::STRING_OR_INT => "VARCHAR(255)",
|
||||||
KeyType::STRING => "VARCHAR(255)",
|
KeyType::STRING => "VARCHAR(255)",
|
||||||
KeyType::INT => "BIGINT",
|
KeyType::INT => "BIGINT",
|
||||||
};
|
};
|
||||||
$valueType = match ($config->annotation->valueType) {
|
$valueType = match ($config->valueType) {
|
||||||
ValueType::INT => "BIGINT",
|
ValueType::INT => "BIGINT",
|
||||||
ValueType::STRING => "VARCHAR(255)",
|
ValueType::STRING => "VARCHAR(255)",
|
||||||
default => "BYTEA",
|
default => "BYTEA",
|
||||||
};
|
};
|
||||||
$serializer = match ($config->annotation->valueType) {
|
$serializer = match ($config->valueType) {
|
||||||
ValueType::INT, ValueType::STRING => $serializer,
|
ValueType::INT, ValueType::STRING => $serializer,
|
||||||
default => new ByteaSerializer($serializer)
|
default => new ByteaSerializer($serializer)
|
||||||
};
|
};
|
||||||
@ -114,6 +114,7 @@ class PostgresArray extends SqlArray
|
|||||||
$expected = $valueType;
|
$expected = $valueType;
|
||||||
} else {
|
} else {
|
||||||
$this->db->query("ALTER TABLE \"bytea_{$config->table}\" DROP \"$key\"");
|
$this->db->query("ALTER TABLE \"bytea_{$config->table}\" DROP \"$key\"");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if ($expected !== $type || $null !== 'NO') {
|
if ($expected !== $type || $null !== 'NO') {
|
||||||
$this->db->query("ALTER TABLE \"bytea_{$config->table}\" MODIFY \"$key\" $expected NOT NULL");
|
$this->db->query("ALTER TABLE \"bytea_{$config->table}\" MODIFY \"$key\" $expected NOT NULL");
|
||||||
|
@ -51,7 +51,7 @@ final class RedisArray extends DriverArray
|
|||||||
|
|
||||||
public function __construct(FieldConfig $config, Serializer $serializer)
|
public function __construct(FieldConfig $config, Serializer $serializer)
|
||||||
{
|
{
|
||||||
if ($serializer instanceof Passthrough && $config->annotation->valueType === ValueType::INT) {
|
if ($serializer instanceof Passthrough && $config->valueType === ValueType::INT) {
|
||||||
$serializer = new IntString;
|
$serializer = new IntString;
|
||||||
}
|
}
|
||||||
parent::__construct($config, $serializer);
|
parent::__construct($config, $serializer);
|
||||||
@ -60,7 +60,6 @@ final class RedisArray extends DriverArray
|
|||||||
\assert($config->settings instanceof Redis);
|
\assert($config->settings instanceof Redis);
|
||||||
$dbKey = $config->settings->getDbIdentifier();
|
$dbKey = $config->settings->getDbIdentifier();
|
||||||
$lock = self::$mutex->acquire($dbKey);
|
$lock = self::$mutex->acquire($dbKey);
|
||||||
\assert($config->settings instanceof Redis);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!isset(self::$connections[$dbKey])) {
|
if (!isset(self::$connections[$dbKey])) {
|
||||||
@ -84,8 +83,10 @@ final class RedisArray extends DriverArray
|
|||||||
foreach ($request as $oldKey) {
|
foreach ($request as $oldKey) {
|
||||||
$newKey = $to.\substr($oldKey, $lenK);
|
$newKey = $to.\substr($oldKey, $lenK);
|
||||||
$value = $this->db->get($oldKey);
|
$value = $this->db->get($oldKey);
|
||||||
$this->db->set($newKey, $value);
|
if ($value !== null) {
|
||||||
$this->db->delete($oldKey);
|
$this->db->set($newKey, $value);
|
||||||
|
$this->db->delete($oldKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,11 +111,11 @@ final class RedisArray extends DriverArray
|
|||||||
$this->db->set($this->rKey((string) $key), $this->serializer->serialize($value));
|
$this->db->set($this->rKey((string) $key), $this->serializer->serialize($value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(mixed $offset): mixed
|
public function get(mixed $key): mixed
|
||||||
{
|
{
|
||||||
$offset = (string) $offset;
|
$key = (string) $key;
|
||||||
|
|
||||||
$value = $this->db->get($this->rKey($offset));
|
$value = $this->db->get($this->rKey($key));
|
||||||
|
|
||||||
if ($value !== null) {
|
if ($value !== null) {
|
||||||
$value = $this->serializer->deserialize($value);
|
$value = $this->serializer->deserialize($value);
|
||||||
|
@ -30,6 +30,7 @@ final class ByteaSerializer implements Serializer
|
|||||||
}
|
}
|
||||||
public function serialize(mixed $value): mixed
|
public function serialize(mixed $value): mixed
|
||||||
{
|
{
|
||||||
|
/** @psalm-suppress MixedArgument */
|
||||||
return new PostgresByteA($this->inner->serialize($value));
|
return new PostgresByteA($this->inner->serialize($value));
|
||||||
}
|
}
|
||||||
public function deserialize(mixed $value): mixed
|
public function deserialize(mixed $value): mixed
|
||||||
|
@ -20,7 +20,11 @@ namespace danog\AsyncOrm\Serializer;
|
|||||||
|
|
||||||
use danog\AsyncOrm\Serializer;
|
use danog\AsyncOrm\Serializer;
|
||||||
|
|
||||||
/** Igbinary serializer. */
|
/**
|
||||||
|
* Igbinary serializer.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
final class Igbinary implements Serializer
|
final class Igbinary implements Serializer
|
||||||
{
|
{
|
||||||
public function serialize(mixed $value): mixed
|
public function serialize(mixed $value): mixed
|
||||||
@ -29,6 +33,7 @@ final class Igbinary implements Serializer
|
|||||||
}
|
}
|
||||||
public function deserialize(mixed $value): mixed
|
public function deserialize(mixed $value): mixed
|
||||||
{
|
{
|
||||||
|
assert(is_string($value));
|
||||||
return \igbinary_unserialize($value);
|
return \igbinary_unserialize($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,11 @@ namespace danog\AsyncOrm\Serializer;
|
|||||||
|
|
||||||
use danog\AsyncOrm\Serializer;
|
use danog\AsyncOrm\Serializer;
|
||||||
|
|
||||||
/** Integer casting serializer */
|
/**
|
||||||
|
* Integer casting serializer
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
final class IntString implements Serializer
|
final class IntString implements Serializer
|
||||||
{
|
{
|
||||||
public function serialize(mixed $value): mixed
|
public function serialize(mixed $value): mixed
|
||||||
|
@ -20,7 +20,11 @@ namespace danog\AsyncOrm\Serializer;
|
|||||||
|
|
||||||
use danog\AsyncOrm\Serializer;
|
use danog\AsyncOrm\Serializer;
|
||||||
|
|
||||||
/** JSON serializer */
|
/**
|
||||||
|
* JSON serializer
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
final class Json implements Serializer
|
final class Json implements Serializer
|
||||||
{
|
{
|
||||||
public function serialize(mixed $value): mixed
|
public function serialize(mixed $value): mixed
|
||||||
@ -29,6 +33,7 @@ final class Json implements Serializer
|
|||||||
}
|
}
|
||||||
public function deserialize(mixed $value): mixed
|
public function deserialize(mixed $value): mixed
|
||||||
{
|
{
|
||||||
|
assert(is_string($value));
|
||||||
return \json_decode($value, true, flags: JSON_THROW_ON_ERROR);
|
return \json_decode($value, true, flags: JSON_THROW_ON_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,11 @@ namespace danog\AsyncOrm\Serializer;
|
|||||||
|
|
||||||
use danog\AsyncOrm\Serializer;
|
use danog\AsyncOrm\Serializer;
|
||||||
|
|
||||||
/** Native serializer */
|
/**
|
||||||
|
* Native serializer
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
final class Native implements Serializer
|
final class Native implements Serializer
|
||||||
{
|
{
|
||||||
public function serialize(mixed $value): mixed
|
public function serialize(mixed $value): mixed
|
||||||
@ -29,6 +33,7 @@ final class Native implements Serializer
|
|||||||
}
|
}
|
||||||
public function deserialize(mixed $value): mixed
|
public function deserialize(mixed $value): mixed
|
||||||
{
|
{
|
||||||
|
assert(is_string($value));
|
||||||
return \unserialize($value);
|
return \unserialize($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,11 @@ namespace danog\AsyncOrm\Serializer;
|
|||||||
|
|
||||||
use danog\AsyncOrm\Serializer;
|
use danog\AsyncOrm\Serializer;
|
||||||
|
|
||||||
/** Passthrough serializer */
|
/**
|
||||||
|
* Passthrough serializer
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
final class Passthrough implements Serializer
|
final class Passthrough implements Serializer
|
||||||
{
|
{
|
||||||
public function serialize(mixed $value): mixed
|
public function serialize(mixed $value): mixed
|
||||||
|
@ -30,6 +30,7 @@ use danog\AsyncOrm\Serializer;
|
|||||||
final readonly class Mysql extends SqlSettings
|
final readonly class Mysql extends SqlSettings
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @param Serializer $serializer to use for object and mixed type values.
|
* @param Serializer $serializer to use for object and mixed type values.
|
||||||
* @param int<0, max> $cacheTtl Cache TTL in seconds, if 0 disables caching.
|
* @param int<0, max> $cacheTtl Cache TTL in seconds, if 0 disables caching.
|
||||||
* @param int<1, max> $maxConnections Maximum connection limit
|
* @param int<1, max> $maxConnections Maximum connection limit
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
namespace danog\AsyncOrm\Settings;
|
namespace danog\AsyncOrm\Settings;
|
||||||
|
|
||||||
use Amp\Postgres\PostgresConfig;
|
use Amp\Postgres\PostgresConfig;
|
||||||
use Amp\Serialization\Serializer;
|
|
||||||
use danog\AsyncOrm\Internal\Driver\PostgresArray;
|
use danog\AsyncOrm\Internal\Driver\PostgresArray;
|
||||||
|
use danog\AsyncOrm\Serializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Postgres backend settings.
|
* Postgres backend settings.
|
||||||
@ -27,6 +27,7 @@ use danog\AsyncOrm\Internal\Driver\PostgresArray;
|
|||||||
final readonly class Postgres extends SqlSettings
|
final readonly class Postgres extends SqlSettings
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @param Serializer $serializer to use for object and mixed type values.
|
* @param Serializer $serializer to use for object and mixed type values.
|
||||||
* @param int<0, max> $cacheTtl Cache TTL in seconds
|
* @param int<0, max> $cacheTtl Cache TTL in seconds
|
||||||
* @param int<1, max> $maxConnections Maximum connection limit
|
* @param int<1, max> $maxConnections Maximum connection limit
|
||||||
|
@ -26,6 +26,8 @@ use danog\AsyncOrm\Serializer;
|
|||||||
final readonly class Redis extends DriverSettings
|
final readonly class Redis extends DriverSettings
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
|
*
|
||||||
* @param Serializer $serializer to use for object and mixed type values.
|
* @param Serializer $serializer to use for object and mixed type values.
|
||||||
* @param int<0, max> $cacheTtl Cache TTL in seconds
|
* @param int<0, max> $cacheTtl Cache TTL in seconds
|
||||||
*/
|
*/
|
||||||
@ -34,7 +36,7 @@ final readonly class Redis extends DriverSettings
|
|||||||
Serializer $serializer,
|
Serializer $serializer,
|
||||||
int $cacheTtl = self::DEFAULT_CACHE_TTL,
|
int $cacheTtl = self::DEFAULT_CACHE_TTL,
|
||||||
) {
|
) {
|
||||||
parent::__construct($cacheTtl, $serializer);
|
parent::__construct($serializer, $cacheTtl);
|
||||||
}
|
}
|
||||||
/** @internal */
|
/** @internal */
|
||||||
public function getDbIdentifier(): string
|
public function getDbIdentifier(): string
|
||||||
|
@ -28,18 +28,6 @@ abstract readonly class SqlSettings extends DriverSettings
|
|||||||
{
|
{
|
||||||
final public const DEFAULT_SQL_MAX_CONNECTIONS = 100;
|
final public const DEFAULT_SQL_MAX_CONNECTIONS = 100;
|
||||||
final public const DEFAULT_SQL_IDLE_TIMEOUT = 60;
|
final public const DEFAULT_SQL_IDLE_TIMEOUT = 60;
|
||||||
/**
|
|
||||||
* Database password.
|
|
||||||
*/
|
|
||||||
public string $database;
|
|
||||||
/**
|
|
||||||
* Database username.
|
|
||||||
*/
|
|
||||||
public string $username;
|
|
||||||
/**
|
|
||||||
* Database password.
|
|
||||||
*/
|
|
||||||
public string $password;
|
|
||||||
/**
|
/**
|
||||||
* Maximum connection limit.
|
* Maximum connection limit.
|
||||||
*
|
*
|
||||||
@ -76,6 +64,6 @@ abstract readonly class SqlSettings extends DriverSettings
|
|||||||
{
|
{
|
||||||
$host = $this->config->getHost();
|
$host = $this->config->getHost();
|
||||||
$port = $this->config->getPort();
|
$port = $this->config->getPort();
|
||||||
return "$host:$port:".$this->config->getDatabase();
|
return "$host:$port:".(string)$this->config->getDatabase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user