Файловое хранилище
Winter даёт персистентное key-value хранилище на файлах с необязательным сроком жизни. Оно доступно из FPM-воркеров, консольных команд и потомков-threads — без Redis. На нём же работают внутренние механизмы: передача данных в джобы, состояние демонов, кеш маршрутов.
Что такое файловое хранилище и зачем
Файловое хранилище — простое key-value на файлах, переживающее рестарт процесса.
Проблема. Иногда нужно сохранить немного данных между запросами или процессами — токены, коды подтверждения, счётчики троттлинга — но поднимать ради этого Redis избыточно.
Решение. Winter даёт файловое хранилище с TTL: положили по ключу, прочитали, пока не истёк срок. Об этом и раздел; для высоконагруженного кеша есть Redis.
Доступ
Kernel отдаёт именованное хранилище тремя методами — они различаются лишь базовой
папкой:
public static function store(string $name, bool $isHash = true): FileStorage // storage/cache
public static function runnable(string $name, bool $isHash = true): FileStorage // storage/runnable
public static function volatile(string $name, bool $isHash = true): FileStorage // storage/volatileДля прикладного кеширования используйте store():
use Flytachi\Winter\K2\Kernel;
$store = Kernel::store('sessions'); // FileStorage в storage/cache/sessionsAPI FileStorage
public function write(string $key, mixed $content, ?int $expireAtTimestamp = null): void
public function read(string $key): mixed // null, если нет или истёк
public function has(string $key): bool
public function del(string $key): void
public function keys(): array
public function clear(): void
public function gc(int $tmpMaxAgeSeconds = 3600): int$store = Kernel::store('sessions');
$store->write('user:42', ['name' => 'Ada']);
$data = $store->read('user:42'); // ['name' => 'Ada'] или null
if ($store->has('user:42')) {
$store->del('user:42');
}Срок жизни (TTL)
Третий аргумент write() — абсолютный UNIX-timestamp истечения, не
относительная длительность:
$store->write('otp:42', '123456', time() + 300); // валиден 5 минут
$code = $store->read('otp:42'); // null после истеченияПустое значение не пишется
write() с «пустым» содержимым ('', 0, null, [], false) — тихий no-op:
такие значения сохранить нельзя. read() возвращает null и для отсутствующего, и
для истёкшего ключа (не бросает). Значения сериализуются, запись атомарна
(tmp-файл + rename), а gc() подчищает осиротевшие .tmp.
Где это используется в ядре
Хранилище — фундамент нескольких механизмов: передача полезной нагрузки в джобы
(dispatch() кладёт данные в volatile), состояние демонов (runnable), кеш
таблицы маршрутов. Ваш код работает с тем же API через Kernel::store().
Файлы vs Redis
| Файловое хранилище | Redis | |
|---|---|---|
| Инфраструктура | не нужна | нужен Redis |
| Для чего | токены, OTP, мелкие кеши | горячий кеш, высокая нагрузка |
| TTL | абсолютный timestamp | нативные команды Redis |
Дальше
- Кеширование — Redis-хранилище для нагрузки
- Джобы — используют хранилище для передачи данных
- Структура проекта — папки
storage/