[CACHE][COMPONENT][Tag] Add generic Cache::pagedStream and use it for the tag stream. Note that it doesn't respect scope yet
This commit is contained in:
parent
6cd86cac25
commit
14c173df7a
@ -4,28 +4,19 @@ namespace Component\Tag\Controller;
|
|||||||
|
|
||||||
use App\Core\Cache;
|
use App\Core\Cache;
|
||||||
use App\Core\Controller;
|
use App\Core\Controller;
|
||||||
use App\Core\DB\DB;
|
|
||||||
use App\Util\Common;
|
|
||||||
use Component\Tag\Tag as CompTag;
|
use Component\Tag\Tag as CompTag;
|
||||||
|
|
||||||
class Tag extends Controller
|
class Tag extends Controller
|
||||||
{
|
{
|
||||||
public function tag(string $tag)
|
public function tag(string $tag)
|
||||||
{
|
{
|
||||||
// TODO scope
|
|
||||||
$per_page = Common::config('streams', 'notes_per_page');
|
|
||||||
$page = $this->int('page') ?: 1;
|
$page = $this->int('page') ?: 1;
|
||||||
$tag = CompTag::canonicalTag($tag);
|
$tag = CompTag::canonicalTag($tag);
|
||||||
$notes = array_reverse( // TODO meme
|
$notes = Cache::pagedStream(
|
||||||
Cache::getList(
|
key: "tag-{$tag}",
|
||||||
"tag-{$tag}",
|
query: 'select n from note n join note_tag nt with nt.note_id = n.id where nt.canonical = :tag order by nt.created DESC, n.id DESC',
|
||||||
fn () => DB::dql(
|
query_args: ['tag' => $tag],
|
||||||
'select n from note n join note_tag nt with nt.note_id = n.id ' .
|
page: $page
|
||||||
'where nt.canonical = :tag order by nt.created ASC, n.id ASC',
|
|
||||||
['tag' => $tag]),
|
|
||||||
offset: $per_page * ($page - 1),
|
|
||||||
limit: $per_page - 1
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
namespace App\Core;
|
namespace App\Core;
|
||||||
|
|
||||||
|
use App\Core\DB\DB;
|
||||||
|
use App\Entity\Note;
|
||||||
use App\Util\Common;
|
use App\Util\Common;
|
||||||
use App\Util\Exception\ConfigurationException;
|
use App\Util\Exception\ConfigurationException;
|
||||||
use Functional as F;
|
use Functional as F;
|
||||||
@ -146,7 +148,7 @@ abstract class Cache
|
|||||||
* Retrieve a list from the cache, with a different implementation
|
* Retrieve a list from the cache, with a different implementation
|
||||||
* for redis and others, trimming to $max_count if given
|
* for redis and others, trimming to $max_count if given
|
||||||
*/
|
*/
|
||||||
public static function getList(string $key, callable $calculate, string $pool = 'default', ?int $max_count = null, ?int $offset = null, ?int $limit = null, float $beta = 1.0): array
|
public static function getList(string $key, callable $calculate, string $pool = 'default', ?int $max_count = null, ?int $left = null, ?int $right = null, float $beta = 1.0): array
|
||||||
{
|
{
|
||||||
if (isset(self::$redis[$pool])) {
|
if (isset(self::$redis[$pool])) {
|
||||||
if (!($recompute = $beta === INF || !(self::$redis[$pool]->exists($key)))) {
|
if (!($recompute = $beta === INF || !(self::$redis[$pool]->exists($key)))) {
|
||||||
@ -169,10 +171,10 @@ abstract class Cache
|
|||||||
$res = $calculate(null, $save);
|
$res = $calculate(null, $save);
|
||||||
if ($save) {
|
if ($save) {
|
||||||
self::setList($key, $res, $pool, $max_count, $beta);
|
self::setList($key, $res, $pool, $max_count, $beta);
|
||||||
return array_slice($res, $offset ?? 0, $limit);
|
return array_slice($res, $left ?? 0, $right - ($left ?? 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self::$redis[$pool]->lRange($key, $offset ?? 0, ($offset ?? 0) + ($limit ?? $max_count ?? -1));
|
return self::$redis[$pool]->lRange($key, $left ?? 0, ($right ?? $max_count ?? 0) - 1);
|
||||||
} else {
|
} else {
|
||||||
return self::get($key, function () use ($calculate, $max_count) {
|
return self::get($key, function () use ($calculate, $max_count) {
|
||||||
$res = $calculate(null);
|
$res = $calculate(null);
|
||||||
@ -212,7 +214,7 @@ abstract class Cache
|
|||||||
self::$redis[$pool]
|
self::$redis[$pool]
|
||||||
// doesn't need to be atomic, adding at one end, deleting at the other
|
// doesn't need to be atomic, adding at one end, deleting at the other
|
||||||
->multi(Redis::PIPELINE)
|
->multi(Redis::PIPELINE)
|
||||||
->rPush($key, $value)
|
->lPush($key, $value)
|
||||||
// trim to $max_count, if given
|
// trim to $max_count, if given
|
||||||
->lTrim($key, -$max_count ?? 0, -1)
|
->lTrim($key, -$max_count ?? 0, -1)
|
||||||
->exec();
|
->exec();
|
||||||
@ -238,4 +240,45 @@ abstract class Cache
|
|||||||
return self::delete($key, $pool);
|
return self::delete($key, $pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null|callable(int $offset, int $lenght): Note[] $getter
|
||||||
|
*/
|
||||||
|
public static function pagedStream(string $key, ?callable $getter = null, ?string $query = null, array $query_args = null, int $page = 1, ?int $per_page = null, string $pool = 'default', ?int $max_count = null, float $beta = 1.0)
|
||||||
|
{
|
||||||
|
// TODO scope
|
||||||
|
|
||||||
|
if (is_null($per_page)) {
|
||||||
|
$per_page = Common::config('streams', 'notes_per_page');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_null($max_count) && $per_page > $max_count || !(is_null($getter) ^ is_null($query))) {
|
||||||
|
throw new \InvalidArgumentException;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_callable($getter)) {
|
||||||
|
$getter = function (int $offset, int $lenght) use ($query, $query_args) {
|
||||||
|
return DB::dql($query, $query_args, options: ['offset' => $offset, 'limit' => $lenght]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$requested_left = $offset = $per_page * ($page - 1);
|
||||||
|
$requested_right = $requested_left + $per_page;
|
||||||
|
[$stored_left, $stored_right] = F\map(explode(':', self::get("{$key}-bounds", fn () => "{$requested_left}:{$requested_right}")), fn (string $v) => (int) $v);
|
||||||
|
$lenght = $stored_right - $stored_left;
|
||||||
|
|
||||||
|
if (!is_null($max_count) && $lenght > $max_count) {
|
||||||
|
$lenght = $max_count;
|
||||||
|
$requested_right = $requested_left + $max_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($stored_left > $requested_left || $stored_right < $requested_right) {
|
||||||
|
$res = $getter($stored_left, $stored_right);
|
||||||
|
self::setList($key, value: $res, pool: $pool, max_count: $max_count, beta: $beta);
|
||||||
|
self::set("{$key}-bounds", "{$stored_left}:{$stored_right}");
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::getList($key, fn () => $getter($requested_left, $lenght), max_count: $max_count, left: $requested_left, right: $requested_right, beta: $beta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user