101 lines
3.0 KiB
PHP
101 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace XBotControl;
|
|
|
|
use Clue\React\SQLite\DatabaseInterface;
|
|
use React\Promise\PromiseInterface;
|
|
use Clue\React\SQLite\Result;
|
|
|
|
class Storage
|
|
{
|
|
protected static $instance;
|
|
/** @var DatabaseInterface $db */
|
|
public $db;
|
|
public $cache = [];
|
|
|
|
protected static $tablesCache = [
|
|
'ip',
|
|
'domain',
|
|
'useragent',
|
|
'headers',
|
|
'path'
|
|
];
|
|
|
|
public function __construct()
|
|
{
|
|
$this->db = (new \Clue\React\SQLite\Factory())->openLazy($_ENV['APP_DIR'] . '/requests.db');
|
|
|
|
foreach (self::$tablesCache as $cacheParition) {
|
|
$this->cache[$cacheParition] = new \React\Cache\ArrayCache(1000);
|
|
}
|
|
}
|
|
|
|
public static function getInstance(): Storage
|
|
{
|
|
if (self::$instance === null) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public static function getId(string $cacheParition, string $key): PromiseInterface
|
|
{
|
|
$storage = self::getInstance();
|
|
|
|
/* if (!isset(self::$tablesCache[$cacheParition])) {
|
|
return $storage::insert($cacheParition, ['data' => $key])->then(function ($result) {
|
|
return $result->rows["0"][$result->columns['0']];
|
|
});
|
|
} */
|
|
|
|
|
|
return $storage->cache[$cacheParition]->get($key)
|
|
->then(function ($result) use ($storage, $cacheParition, $key) {
|
|
if ($result === null) {
|
|
return self::insertAndCache($storage, $cacheParition, $key);
|
|
}
|
|
return (int) $result;
|
|
}, function () {
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
|
|
private static function insertAndCache(Storage $storage, string $cacheParition, string $key): PromiseInterface
|
|
{
|
|
|
|
$query = "INSERT INTO $cacheParition (data) VALUES (?) ON CONFLICT(data) DO UPDATE SET data=? RETURNING rowid ;";
|
|
|
|
return $storage->db
|
|
->query($query, [$key, $key])
|
|
->then(function (Result $result) use ($storage, $cacheParition, $key) {
|
|
|
|
return self::cache($storage, $cacheParition, $key, $result);
|
|
});
|
|
}
|
|
|
|
private static function cache(Storage $storage, string $cacheParition, string $key, Result $result): PromiseInterface
|
|
{
|
|
$value = $result->rows["0"][$result->columns['0']];
|
|
return $storage->cache[$cacheParition]->set($key, $value)
|
|
->then(function () use ($value) {
|
|
return $value;
|
|
});
|
|
}
|
|
|
|
public static function insert(string $table, array $values): PromiseInterface
|
|
{
|
|
$columns = implode(", ", array_keys($values));
|
|
$placeholders = implode(", ", array_fill(0, count($values), "?"));
|
|
$query = sprintf("INSERT INTO %s (%s) VALUES (%s);", $table, $columns, $placeholders);
|
|
$params = array_values($values);
|
|
|
|
$storage = self::getInstance();
|
|
return $storage->db->query($query, $params)->then(function (Result $result) {
|
|
return $result->insertId;
|
|
});
|
|
}
|
|
}
|