Caching but it's procedural now.

This commit is contained in:
flash 2018-10-07 00:40:14 +02:00
parent a480678b11
commit fb93b908c9
4 changed files with 139 additions and 137 deletions

View file

@ -28,6 +28,7 @@ $errorHandler->register();
require_once 'src/array.php'; require_once 'src/array.php';
require_once 'src/audit_log.php'; require_once 'src/audit_log.php';
require_once 'src/cache.php';
require_once 'src/changelog.php'; require_once 'src/changelog.php';
require_once 'src/colour.php'; require_once 'src/colour.php';
require_once 'src/comments.php'; require_once 'src/comments.php';
@ -244,14 +245,7 @@ MIG;
exit; exit;
} }
new Cache( cache_init(config_get_default([], 'Cache'));
config_get('Cache', 'host'),
config_get('Cache', 'port'),
config_get('Cache', 'database'),
config_get('Cache', 'password'),
config_get_default('', 'Cache', 'prefix')
);
geoip_init(config_get_default('', 'GeoIP', 'database_path')); geoip_init(config_get_default('', 'GeoIP', 'database_path'));
tpl_init([ tpl_init([

View file

@ -33,7 +33,7 @@ $news = Database::query('
LIMIT 5 LIMIT 5
')->fetchAll(PDO::FETCH_ASSOC); ')->fetchAll(PDO::FETCH_ASSOC);
$statistics = Cache::instance()->get('index:stats:v1', function () { $statistics = cache_get('index:stats:v1', function () {
return [ return [
'users' => (int)Database::query(' 'users' => (int)Database::query('
SELECT COUNT(`user_id`) SELECT COUNT(`user_id`)
@ -52,7 +52,7 @@ $statistics = Cache::instance()->get('index:stats:v1', function () {
]; ];
}, 10800); }, 10800);
$changelog = Cache::instance()->get('index:changelog:v1', function () { $changelog = cache_get('index:changelog:v1', function () {
return Database::query(' return Database::query('
SELECT SELECT
c.`change_id`, c.`change_log`, c.`change_id`, c.`change_log`,
@ -67,7 +67,7 @@ $changelog = Cache::instance()->get('index:changelog:v1', function () {
')->fetchAll(PDO::FETCH_ASSOC); ')->fetchAll(PDO::FETCH_ASSOC);
}, 1800); }, 1800);
$onlineUsers = Cache::instance()->get('index:online:v1', function () { $onlineUsers = cache_get('index:online:v1', function () {
return Database::query(' return Database::query('
SELECT SELECT
u.`user_id`, u.`username`, u.`user_id`, u.`username`,

View file

@ -1,126 +0,0 @@
<?php
namespace Misuzu;
use Redis;
use InvalidArgumentException;
use UnexpectedValueException;
final class Cache
{
/**
* @var Cache
*/
private static $instance;
private $redis;
public static function instance(): Cache
{
if (!self::hasInstance()) {
throw new UnexpectedValueException('No instance of Cache exists yet.');
}
return self::$instance;
}
public function getRedis(): Redis
{
return $this->redis;
}
public static function hasInstance(): bool
{
return self::$instance instanceof static;
}
public function __construct(
string $host,
?int $port = null,
?int $database = null,
?string $password = null,
string $prefix = ''
) {
if (self::hasInstance()) {
throw new UnexpectedValueException('Only one instance of Cache may exist.');
}
self::$instance = $this;
$this->redis = new Redis;
$this->redis->connect($host, $port);
if ($password !== null && !$this->redis->auth($password)) {
throw new InvalidArgumentException('Redis auth failed.');
}
if ($database !== null && !$this->redis->select($database)) {
throw new UnexpectedValueException('Redis select failed.');
}
$this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$this->redis->setOption(Redis::OPT_PREFIX, $prefix);
}
public function __destruct()
{
$this->redis->close();
self::$instance = null;
}
public function set(string $key, $value, int $ttl = 0)
{
if (is_callable($value)) {
$value = $value();
}
if ($ttl < 0) {
return $value;
} elseif ($ttl < 1) {
$this->redis->set($key, $value);
} else {
$this->redis->setEx($key, $ttl, $value);
}
return $value;
}
public function exists(string $key): bool
{
return $this->redis->exists($key);
}
public function delete($keys): int
{
return $this->redis->delete($keys);
}
public function increment(string $key, int $amount = 1): int
{
if ($amount <= 1) {
return $this->redis->incr($key);
}
return $this->redis->incrBy($key, $amount);
}
public function decrement(string $key, int $amount = 1): int
{
if ($amount <= 1) {
return $this->redis->decr($key);
}
return $this->redis->decrBy($key, $amount);
}
public function get(string $key, $fallback, int $ttl = 0)
{
if ($ttl < 0) {
return is_callable($fallback) ? $fallback() : $fallback;
}
if (!$this->exists($key)) {
return $this->set($key, $fallback, $ttl);
}
return $this->redis->get($key);
}
}

134
src/cache.php Normal file
View file

@ -0,0 +1,134 @@
<?php
define('MSZ_CACHE_REDIS_STORE', '_msz_cache_redis');
define('MSZ_CACHE_OPTIONS_STORE', '_msz_cache_options');
define('MSZ_CACHE_INIT_OK', 0);
define('MSZ_CACHE_INIT_ACTIVE', 1);
define('MSZ_CACHE_INIT_FAIL', 2);
define('MSZ_CACHE_INIT_AUTH', 3);
define('MSZ_CACHE_INIT_DATABASE', 4);
function cache_init(array $options, bool $start = false): void
{
$GLOBALS[MSZ_CACHE_OPTIONS_STORE] = $options;
if ($start) {
cache_start();
}
}
function cache_start(?array $options = null): bool
{
if (!empty($GLOBALS[MSZ_CACHE_REDIS_STORE])) {
return MSZ_CACHE_INIT_ACTIVE;
}
if ($options === null) {
$options = $GLOBALS[MSZ_CACHE_OPTIONS_STORE] ?? [];
}
if (empty($options['host'])) {
// if no host is present we just act as a void
return MSZ_CACHE_INIT_OK;
}
$redis = new Redis;
if (!$redis->connect($options['host'], $options['port'] ?? null)) {
return MSZ_CACHE_INIT_FAIL;
}
if (!empty($options['password']) && !$redis->auth($options['password'])) {
return MSZ_CACHE_INIT_AUTH;
}
if (!empty($options['database']) && !$redis->select($options['database'])) {
return MSZ_CACHE_INIT_DATABASE;
}
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$redis->setOption(Redis::OPT_PREFIX, $options['prefix'] ?? '');
$GLOBALS[MSZ_CACHE_REDIS_STORE] = $redis;
return MSZ_CACHE_INIT_OK;
}
function cache_available(): bool
{
if (!empty($GLOBALS[MSZ_CACHE_REDIS_STORE])) {
return true;
}
$startUp = cache_start();
return $startUp === MSZ_CACHE_INIT_OK || $startUp === MSZ_CACHE_INIT_ACTIVE;
}
function cache_exists(string $key): bool
{
return cache_available() && $GLOBALS[MSZ_CACHE_REDIS_STORE]->exists($key);
}
function cache_remove($keys): int
{
if (!cache_available()) {
return 0;
}
return $GLOBALS[MSZ_CACHE_REDIS_STORE]->delete($keys);
}
function cache_get(string $key, $fallback, int $ttl = 0)
{
if (!cache_available() || $ttl < 0) {
return is_callable($fallback) ? $fallback() : $fallback;
}
if (!cache_exists($key)) {
return cache_set($key, $fallback, $ttl);
}
return $GLOBALS[MSZ_CACHE_REDIS_STORE]->get($key);
}
function cache_set(string $key, $value, int $ttl = 0)
{
if (is_callable($value)) {
$value = $value();
}
if (!cache_available() || $ttl < 0) {
return $value;
} elseif ($ttl < 1) {
$GLOBALS[MSZ_CACHE_REDIS_STORE]->set($key, $value);
} else {
$GLOBALS[MSZ_CACHE_REDIS_STORE]->setEx($key, $ttl, $value);
}
return $value;
}
function cache_increment(string $key, int $amount = 1): int
{
if (!cache_available()) {
return abs($amount);
}
if ($amount <= 1) {
return $GLOBALS[MSZ_CACHE_REDIS_STORE]->incr($key);
}
return $GLOBALS[MSZ_CACHE_REDIS_STORE]->incrBy($key, $amount);
}
function cache_decrement(string $key, int $amount = 1): int
{
if (!cache_available()) {
return abs($amount) * -1;
}
if ($amount <= 1) {
return $GLOBALS[MSZ_CACHE_REDIS_STORE]->decr($key);
}
return $GLOBALS[MSZ_CACHE_REDIS_STORE]->decrBy($key, $amount);
}