refac: KVStorage의 내부구조를 Ds\Map으로 변경

This commit is contained in:
2022-05-08 20:10:04 +09:00
parent 703bf9395d
commit bf2268ee4a
7 changed files with 166 additions and 145 deletions
+1 -1
View File
@@ -41,7 +41,7 @@ function processSpring() {
function processGoldIncome() { function processGoldIncome() {
$db = DB::db(); $db = DB::db();
$gameStor = new KVStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']); [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$adminLog = []; $adminLog = [];
@@ -52,7 +52,7 @@ class ResetTurnTime extends \sammo\BaseAPI
return '충분한 유산 포인트를 가지고 있지 않습니다.'; return '충분한 유산 포인트를 가지고 있지 않습니다.';
} }
$gameStor = new KVStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
[$turnTerm, $serverTurnTime] = $gameStor->getValuesAsArray(['turnterm', 'turntime']); [$turnTerm, $serverTurnTime] = $gameStor->getValuesAsArray(['turnterm', 'turntime']);
$currTurnTime = new DateTimeImmutable($general->getTurnTime()); $currTurnTime = new DateTimeImmutable($general->getTurnTime());
+1 -1
View File
@@ -47,7 +47,7 @@ class SetBlockScout extends \sammo\BaseAPI
return "권한이 부족합니다."; return "권한이 부족합니다.";
} }
$gameStor = new KVStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$blockChangeScout = $gameStor->getValue('block_change_scout')??false; $blockChangeScout = $gameStor->getValue('block_change_scout')??false;
if ($blockChangeScout){ if ($blockChangeScout){
return "임관 설정을 바꿀 수 없도록 설정되어 있습니다."; return "임관 설정을 바꿀 수 없도록 설정되어 있습니다.";
+1 -1
View File
@@ -15,7 +15,7 @@ class BlockScoutAction extends \sammo\Event\Action{
'scout'=>1 'scout'=>1
], true); ], true);
if($this->blockChangeScout !== null){ if($this->blockChangeScout !== null){
$gameStor = new KVStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->setValue('block_change_scout', $this->blockChangeScout); $gameStor->setValue('block_change_scout', $this->blockChangeScout);
} }
@@ -16,7 +16,7 @@ class UnblockScoutAction extends \sammo\Event\Action{
]); ]);
if($this->blockChangeScout !== null){ if($this->blockChangeScout !== null){
$gameStor = new KVStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->setValue('block_change_scout', $this->blockChangeScout); $gameStor->setValue('block_change_scout', $this->blockChangeScout);
} }
+136 -140
View File
@@ -1,211 +1,202 @@
<?php <?php
namespace sammo; namespace sammo;
use MeekroDBException; use MeekroDBException;
use Ds\Map;
class KVStorage{ class KVStorage
{
private $db; private $db;
private $tableName; private $tableName;
private $storNamespace; private $storNamespace;
private $cacheData = null;
static private $storageList = []; private ?Map $cacheData = null;
static private function convBackedEnum(string|int|\BackedEnum $key): string|int{ /** @var null|Map<string, self> */
if($key instanceof \BackedEnum){ static private ?Map $storageList = null;
return $key->value;
static public function getStorage(\MeekroDB $db, $storNamespace, string $tableName = 'storage'): self
{
if (self::$storageList === null) {
self::$storageList = new Map();
} }
return $key;
}
/**
* @param (string|int|\BackedEnum)[] $keys
* @return (string|int)[]
*/
static private function convBackedEnums(array $keys): array{
$convKeys = [];
foreach($keys as $key){
if($key instanceof \BackedEnum){
$convKeys[] = $key->value;
}
else{
$convKeys[] = $key;
}
}
return $convKeys;
}
static public function getStorage(\MeekroDB $db, $storNamespace, string $tableName='storage'):self{
$obj_id = spl_object_hash($db); $obj_id = spl_object_hash($db);
$fullKey = $obj_id.','.$storNamespace.','.$tableName; $fullKey = $obj_id . ',' . $storNamespace . ',' . $tableName;
if(key_exists($fullKey, static::$storageList)){ if (self::$storageList->hasKey($fullKey)) {
return static::$storageList[$fullKey]; return self::$storageList[$fullKey];
} }
$obj = new static($db, $storNamespace, $tableName); $obj = new static($db, $storNamespace, $tableName);
static::$storageList[$fullKey] = $obj; self::$storageList[$fullKey] = $obj;
return $obj; return $obj;
} }
public function __construct(\MeekroDB $db, $storNamespace, string $tableName='storage'){ protected function __construct(\MeekroDB $db, $storNamespace, string $tableName = 'storage')
{
$this->db = $db; $this->db = $db;
$this->storNamespace = $storNamespace; $this->storNamespace = $storNamespace;
$this->tableName = $tableName; $this->tableName = $tableName;
$this->turnOnCache(); $this->turnOnCache();
} }
public static function getValuesFromInterNamespace(\MeekroDB $db, string $tableName, string|int|\BackedEnum $key):array{ public static function getValuesFromInterNamespace(\MeekroDB $db, string $tableName, string|int|\BackedEnum $key): array
{
$result = []; $result = [];
$key = self::convBackedEnum($key); $key = Util::valueFromEnum($key);
foreach($db->queryAllLists( foreach ($db->queryAllLists(
'SELECT `namespace`, `value` FROM %b WHERE `key`=%s', $tableName, $key 'SELECT `namespace`, `value` FROM %b WHERE `key`=%s',
) as [$namespaceName, $value]) $tableName,
{ $key
) as [$namespaceName, $value]) {
$result[$namespaceName] = Json::decode($value); $result[$namespaceName] = Json::decode($value);
} }
return $result; return $result;
} }
public function __get(string|int|\BackedEnum $key) { public function __get(string|int|\BackedEnum $key)
{
return $this->getValue($key); return $this->getValue($key);
} }
public function __set(string|int|\BackedEnum $key, $value) { public function __set(string|int|\BackedEnum $key, $value)
{
$this->setValue($key, $value); $this->setValue($key, $value);
} }
public function __unset(string|int|\BackedEnum $key){ public function __unset(string|int|\BackedEnum $key)
{
$this->deleteValue($key); $this->deleteValue($key);
} }
public function turnOnCache(): self{ public function turnOnCache(): self
if($this->cacheData === null){ {
$this->cacheData = []; if ($this->cacheData === null) {
$this->cacheData = new Map();
} }
return $this; return $this;
} }
public function turnOffCache(): self{ public function turnOffCache(): self
if($this->cacheData !== null){ {
if ($this->cacheData !== null) {
$this->cacheData = null; $this->cacheData = null;
} }
return $this; return $this;
} }
public function resetCache(bool $disableCache=true):self{ public function resetCache(bool $disableCache = true): self
if($disableCache){ {
if ($disableCache) {
$this->cacheData = null; $this->cacheData = null;
} } else {
else{
$this->cacheData = []; $this->cacheData = [];
} }
return $this; return $this;
} }
public function resetValues():self{ public function resetValues(): self
if($this->cacheData !== null){ {
if ($this->cacheData !== null) {
$this->cacheData = []; $this->cacheData = [];
} }
return $this->resetDBNamespace(); return $this->resetDBNamespace();
} }
public function invalidateCacheValue(string|int|\BackedEnum $key):self{ public function invalidateCacheValue(string|int|\BackedEnum $key): self
if($this->cacheData === null){ {
if ($this->cacheData === null) {
return $this; return $this;
} }
$key = static::convBackedEnum($key); $key = Util::valueFromEnum($key);
if(key_exists($key, $this->cacheData)){ $this->cacheData->remove($key, null);
unset($this->cacheData[$key]);
}
return $this; return $this;
} }
public function invalidateCacheValues(array $keys):self{ public function invalidateCacheValues(array $keys): self
if($this->cacheData === null){ {
if ($this->cacheData === null) {
return $this; return $this;
} }
$keys = static::convBackedEnums($keys); $keys = Util::valuesFromEnumArray($keys);
foreach($keys as $key){ foreach ($keys as $key) {
if(key_exists($key, $this->cacheData)){ $this->cacheData->remove($key, null);
unset($this->cacheData[$key]);
}
} }
return $this; return $this;
} }
public function cacheAll(bool $invalidateAll=true):self{ public function cacheAll(bool $invalidateAll = true): self
if(!$invalidateAll && $this->cacheData !== null && count($this->cacheData)>0){ {
if (!$invalidateAll && $this->cacheData !== null && count($this->cacheData) > 0) {
return $this; return $this;
} }
$this->cacheData = $this->getDBAll(); $this->cacheData = $this->getDBAll();
return $this; return $this;
} }
public function cacheValues(array $keys, bool $invalidateAll=false):self{ public function cacheValues(array $keys, bool $invalidateAll = false): self
if($this->cacheData === null){ {
$this->cacheData = []; if ($this->cacheData === null) {
$this->cacheData = new Map();
} }
$keys = self::convBackedEnums($keys); $keys = Util::valuesFromEnumArray($keys);
if($invalidateAll){ if ($invalidateAll) {
$notExists = $keys; $notExists = $keys;
} } else {
else{
$notExists = []; $notExists = [];
foreach($keys as $key){ foreach ($keys as $key) {
if(!key_exists($key, $this->cacheData)){ if (!$this->cacheData->hasKey($key)) {
$notExists[] = $key; $notExists[] = $key;
} }
} }
if(!$notExists){ if (!$notExists) {
return $this; return $this;
} }
} }
$values = $this->getDBValues($notExists); $values = $this->getDBValues($notExists);
foreach($notExists as $key){ foreach ($notExists as $key) {
if(key_exists($key, $values)){ $this->cacheData[$key] = $values->get($key, null);
$this->cacheData[$key] = $values[$key];
}
else{
$this->cacheData[$key] = null;
}
} }
return $this; return $this;
} }
public function getAll(bool $onlyCache=false): array{ public function getAll(bool $onlyCache = false): array
if($onlyCache && $this->cacheData !== null && count($this->cacheData) > 0){ {
return $this->cacheData; if ($onlyCache && $this->cacheData !== null && count($this->cacheData) > 0) {
return $this->cacheData->toArray();
} }
$result = $this->getDBAll(); $result = $this->getDBAll();
if($this->cacheData !== null){ if ($this->cacheData !== null) {
$this->cacheData = $result; $this->cacheData = $result;
} }
return $result; return $result->toArray();
} }
public function getValuesAsArray(array $keys, bool $onlyCache=false): array{ public function getValuesAsArray(array $keys, bool $onlyCache = false): array
if(!$keys){ {
if (!$keys) {
return []; return [];
} }
$keys = static::convBackedEnums($keys); $keys = Util::valuesFromEnumArray($keys);
$dictResult = $this->getValues($keys, $onlyCache); $dictResult = $this->getValues($keys, $onlyCache);
$result = []; $result = [];
foreach($keys as $key){ foreach ($keys as $key) {
$result[] = $dictResult[$key]??null; $result[] = $dictResult[$key] ?? null;
} }
return $result; return $result;
} }
public function getValues(array $keys, bool $onlyCache=false): array{ public function getValues(array $keys, bool $onlyCache = false): array
if(!$keys){ {
if (!$keys) {
return []; return [];
} }
$keys = static::convBackedEnums($keys); $keys = Util::valuesFromEnumArray($keys);
if ($this->cacheData === null) { if ($this->cacheData === null) {
return $this->getDBValues($keys); return $this->getDBValues($keys);
@@ -215,9 +206,9 @@ class KVStorage{
$notExists = []; $notExists = [];
//TODO: DB Select에서 as를 쓸 수 있으면 좋을 듯. //TODO: DB Select에서 as를 쓸 수 있으면 좋을 듯.
foreach($keys as $key){ foreach ($keys as $key) {
if(!key_exists($key, $this->cacheData)){ if (!$this->cacheData->hasKey($key)) {
$notExists[] = $key; $notExists[] = $key;
continue; continue;
} }
@@ -225,8 +216,8 @@ class KVStorage{
$result[$key] = $this->cacheData[$key]; $result[$key] = $this->cacheData[$key];
} }
if($onlyCache){ if ($onlyCache) {
foreach($notExists as $emptyKey){ foreach ($notExists as $emptyKey) {
$result[$emptyKey] = null; $result[$emptyKey] = null;
} }
@@ -234,21 +225,22 @@ class KVStorage{
} }
$dbResult = $this->getDBValues($notExists); $dbResult = $this->getDBValues($notExists);
foreach($dbResult as $key=>$value){ foreach ($dbResult as $key => $value) {
$result[$key] = $value; $result[$key] = $value;
$this->cacheData[$key] = $value; $this->cacheData[$key] = $value;
} }
return $result; return $result;
} }
public function getValue(string|int|\BackedEnum $key, bool $onlyCache=false){ public function getValue(string|int|\BackedEnum $key, bool $onlyCache = false)
$key = static::convBackedEnum($key); {
if($this->cacheData !== null && ($onlyCache || key_exists($key, $this->cacheData))){ $key = Util::valueFromEnum($key);
return $this->cacheData[$key] ?? null; if ($this->cacheData !== null && ($onlyCache || $this->cacheData->hasKey($key))) {
return $this->cacheData->get($key, null);
} }
$value = $this->getDBValue($key); $value = $this->getDBValue($key);
if($this->cacheData !== null){ if ($this->cacheData !== null) {
$this->cacheData[$key] = $value; $this->cacheData[$key] = $value;
} }
return $value; return $value;
@@ -259,14 +251,15 @@ class KVStorage{
* @return KVStorage * @return KVStorage
* @throws MeekroDBException * @throws MeekroDBException
*/ */
public function setValue(string|int|\BackedEnum $key, $value):self{ public function setValue(string|int|\BackedEnum $key, $value): self
$key = static::convBackedEnum($key); {
$key = Util::valueFromEnum($key);
if($value === null){ if ($value === null) {
return $this->deleteValue($key); return $this->deleteValue($key);
} }
if($this->cacheData){ if ($this->cacheData) {
$this->cacheData[$key] = $value; $this->cacheData[$key] = $value;
} }
return $this->setDBValue($key, $value); return $this->setDBValue($key, $value);
@@ -279,76 +272,78 @@ class KVStorage{
* @return KVStorage * @return KVStorage
* @throws MeekroDBException * @throws MeekroDBException
*/ */
public function deleteValue(string|int|\BackedEnum $key):self{ public function deleteValue(string|int|\BackedEnum $key): self
$key = static::convBackedEnum($key); {
$key = Util::valueFromEnum($key);
if(isset($this->cacheData[$key])){ $this->cacheData->remove($key, null);
unset($this->cacheData[$key]);
}
return $this->deleteDBValue($key); return $this->deleteDBValue($key);
} }
private function getDBAll(): array{ private function getDBAll(): Map
$result = []; {
foreach($this->db->queryAllLists( $result = new Map();
foreach ($this->db->queryAllLists(
'SELECT `key`, `value` FROM %b WHERE `namespace`=%s', 'SELECT `key`, `value` FROM %b WHERE `namespace`=%s',
$this->tableName, $this->tableName,
$this->storNamespace $this->storNamespace
) as list($key, $value)) ) as list($key, $value)) {
{
$result[$key] = Json::decode($value); $result[$key] = Json::decode($value);
} }
return $result; return $result;
} }
private function getDBValues(array $keys): array{ private function getDBValues(array $keys): Map
if(!$keys){ {
return []; if (!$keys) {
return new Map();
} }
$result = []; $result = new Map();
foreach($this->db->queryAllLists( foreach ($this->db->queryAllLists(
'SELECT `key`, `value` FROM %b WHERE `namespace`=%s AND `key` IN %ls', 'SELECT `key`, `value` FROM %b WHERE `namespace`=%s AND `key` IN %ls',
$this->tableName, $this->tableName,
$this->storNamespace, $this->storNamespace,
$keys $keys
) as list($key, $value)) ) as list($key, $value)) {
{
$result[$key] = Json::decode($value); $result[$key] = Json::decode($value);
} }
foreach($keys as $key){ foreach ($keys as $key) {
if(!key_exists($key, $result)){ if (!$result->hasKey($key)) {
$result[$key] = null; $result[$key] = null;
} }
} }
return $result; return $result;
} }
private function getDBValue(string $key){ private function getDBValue(string $key)
{
$value = $this->db->queryFirstField( $value = $this->db->queryFirstField(
'SELECT `value` FROM %b WHERE `namespace`=%s AND `key`=%s', 'SELECT `value` FROM %b WHERE `namespace`=%s AND `key`=%s',
$this->tableName, $this->tableName,
$this->storNamespace, $this->storNamespace,
$key $key
); );
if($value === null){ if ($value === null) {
return null; return null;
} }
return Json::decode($value); return Json::decode($value);
} }
private function setDBValue(string $key, $value):self{ private function setDBValue(string $key, $value): self
if($value === null){ {
if ($value === null) {
return $this->deleteDBValue($key); return $this->deleteDBValue($key);
} }
$this->db->insertUpdate($this->tableName, [ $this->db->insertUpdate($this->tableName, [
'namespace'=>$this->storNamespace, 'namespace' => $this->storNamespace,
'key'=>$key, 'key' => $key,
'value'=>Json::encode($value) 'value' => Json::encode($value)
]); ]);
return $this; return $this;
} }
private function deleteDBValue(string $key):self{ private function deleteDBValue(string $key): self
{
$this->db->delete( $this->db->delete(
$this->tableName, $this->tableName,
'`namespace`=%s AND `key`=%s', '`namespace`=%s AND `key`=%s',
@@ -358,8 +353,9 @@ class KVStorage{
return $this; return $this;
} }
private function resetDBNamespace():self{ private function resetDBNamespace(): self
{
$this->db->delete($this->tableName, 'namespace=%s', $this->storNamespace); $this->db->delete($this->tableName, 'namespace=%s', $this->storNamespace);
return $this; return $this;
} }
} }
+25
View File
@@ -809,4 +809,29 @@ class Util extends \utilphp\util
} }
} }
} }
public static function valueFromEnum(\BackedEnum|string|int $value):string|int{
if($value instanceof \BackedEnum){
return $value->value;
}
return $value;
}
/**
* @param (int|string|\BackedEnum)[] $values
* @return (int|string)[]
*/
public static function valuesFromEnumArray(array $values):array{
$result = [];
foreach($values as $value){
if($value instanceof \BackedEnum){
$result[] = $value->value;
}
else{
$result[] = $value;
}
}
return $result;
}
}; };