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.
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:
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/volatileFor application caching, use store():
use Flytachi\Winter\K2\Kernel;
$store = Kernel::store('sessions'); // a FileStorage in storage/cache/sessionsThe FileStorage API
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$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:
$store->write('otp:42', '123456', time() + 300); // valid for 5 minutes
$code = $store->read('otp:42'); // null once expiredAn 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
- Redis — the connection pool and stores for load
- Processes — they keep their state in it
- Project structure — the
storage/directories