Advanced

File storage

Winter provides a persistent file-based key-value store with an optional lifetime. It is reachable from FPM workers, console commands and child threads — without Redis. The internal machinery runs on it too: passing data into jobs, daemon state, the class-list cache.

This section is being worked on

The page has not yet been checked against the current kernel code: some examples and names may belong to earlier versions. Use it as a guide and verify exact signatures against the sources or through call help.

The section will be rewritten, like the others that have already been reviewed.

Access Kernel::store()Class FileStorageTTL an absolute timestamp

What file storage is and why

File storage is a simple file-based key-value store that survives a process restart.

The problem. Sometimes a little data has to be kept between requests or processes — tokens, confirmation codes, throttling counters — but standing Redis up for that is excessive.

The solution. Winter provides a file store with a TTL: put it under a key, read it until the deadline passes. That is what this page is about; for a high-load cache there is Redis.

Access

Kernel hands back a named store through three methods — they differ only in their base directory:

php
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

For application caching, use store():

php
use Flytachi\Winter\K2\Kernel;

$store = Kernel::store('sessions');   // a FileStorage in storage/cache/sessions

The FileStorage API

php
public function write(string $key, mixed $content, ?int $expireAtTimestamp = null): void
public function read(string $key): mixed        // null when absent or expired
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
php
$store = Kernel::store('sessions');

$store->write('user:42', ['name' => 'Ada']);
$data = $store->read('user:42');        // ['name' => 'Ada'] or null

if ($store->has('user:42')) {
  $store->del('user:42');
}

Lifetime (TTL)

write()’s third argument is an absolute UNIX expiry timestamp, not a relative duration:

php
$store->write('otp:42', '123456', time() + 300);   // valid for 5 minutes
$code = $store->read('otp:42');                     // null once expired

An empty value is not written

write() with “empty” content ('', 0, null, [], false) is a silent no-op: such values cannot be stored. read() returns null both for a missing key and for an expired one (it does not throw). Values are serialised, the write is atomic (a tmp file plus a rename), and gc() sweeps up orphaned .tmp files.

Where the kernel uses it

The store underpins several mechanisms: passing a payload into a job (dispatch() puts the data into volatile), daemon state (runnable), the route-table cache. Your code works with the same API through Kernel::store().

Files vs Redis

File storage Redis
Infrastructure none needed Redis required
What for tokens, OTPs, small caches a hot cache, high load
TTL an absolute timestamp Redis’s native commands

Next