1
0
mirror of https://github.com/vichan-devel/vichan.git synced 2025-01-19 09:27:24 +01:00

Refactor queue.php

This commit is contained in:
Zankaria 2024-02-16 15:18:17 +01:00
parent 55034762b0
commit e61ed35aa0
2 changed files with 95 additions and 38 deletions

View File

@ -2918,8 +2918,16 @@ function generation_strategy($fun, $array=array()) { global $config;
return 'rebuild'; return 'rebuild';
case 'defer': case 'defer':
// Ok, it gets interesting here :) // Ok, it gets interesting here :)
get_queue('generate')->push(serialize(array('build', $fun, $array, $action))); $queue = Queues::get_queue($config, 'generate');
if ($queue === false) {
if ($config['syslog']) {
_syslog(LOG_ERR, "Could not initialize generate queue, falling back to immediate rebuild strategy");
}
return 'rebuild';
} else {
$queue->push(serialize(array('build', $fun, $array, $action)));
return 'ignore'; return 'ignore';
}
case 'build_on_load': case 'build_on_load':
return 'delete'; return 'delete';
} }

View File

@ -1,49 +1,98 @@
<?php <?php
class Queue { class Queues {
function __construct($key) { global $config; private static $queues = array();
if ($config['queue']['enabled'] == 'fs') {
$this->lock = Locks::get_lock($config, $key);
/**
* This queue implementation isn't actually ordered, so it works more as a "bag".
*/
private static function filesystem(string $key, Lock $lock): Queue {
$key = str_replace('/', '::', $key); $key = str_replace('/', '::', $key);
$key = str_replace("\0", '', $key); $key = str_replace("\0", '', $key);
$this->key = "tmp/queue/$key/"; $key = "tmp/queue/$key/";
}
return new class($key, $lock) implements Queue {
private Lock $lock;
private string $key;
function __construct(string $key, Lock $lock) {
$this->lock = $lock;
$this->key = $key;
} }
function push($str) { global $config; public function push(string $str): Queue {
if ($config['queue']['enabled'] == 'fs') {
$this->lock->get_ex(); $this->lock->get_ex();
file_put_contents($this->key.microtime(true), $str); file_put_contents($this->key . microtime(true), $str);
$this->lock->free(); $this->lock->free();
}
return $this; return $this;
} }
function pop($n = 1) { global $config; public function pop(int $n = 1): array {
if ($config['queue']['enabled'] == 'fs') {
$this->lock->get_ex(); $this->lock->get_ex();
$dir = opendir($this->key); $dir = opendir($this->key);
$paths = array(); $paths = array();
while ($n > 0) { while ($n > 0) {
$path = readdir($dir); $path = readdir($dir);
if ($path === FALSE) break; if ($path === false) {
elseif ($path == '.' || $path == '..') continue; break;
else { $paths[] = $path; $n--; } } elseif ($path == '.' || $path == '..') {
continue;
} else {
$paths[] = $path;
$n--;
} }
}
$out = array(); $out = array();
foreach ($paths as $v) { foreach ($paths as $v) {
$out []= file_get_contents($this->key.$v); $out[] = file_get_contents($this->key . $v);
unlink($this->key.$v); unlink($this->key . $v);
} }
$this->lock->free(); $this->lock->free();
return $out; return $out;
} }
};
}
/**
* No-op. Can be used for mocking.
*/
public static function none(): Queue {
return new class() implements Queue {
public function push(string $str): Queue {
return $this;
}
public function pop(int $n = 1): array {
return array();
}
};
}
public static function get_queue(array $config, string $name): Queue|false {
if (!isset(self::$queues[$name])) {
if ($config['queue']['enabled'] == 'fs') {
$lock = Locks::get_lock($config, $name);
if ($lock === false) {
return false;
}
self::$queues[$name] = self::filesystem($name, $lock);
} else {
self::$queues[$name] = self::none();
}
}
return self::$queues[$name];
} }
} }
// Don't use the constructor. Use the get_queue function. interface Queue {
$queues = array(); // Push a string in the queue.
public function push(string $str): Queue;
function get_queue($name) { global $queues; // Get a string from the queue.
return $queues[$name] = isset ($queues[$name]) ? $queues[$name] : new Queue($name); public function pop(int $n = 1): array;
} }