Winter Boot Node-Local In-Memory KV and Queue Stores
Winter Boot ships two lightweight stores — a key-value store and a queue store — that run as child processes next to your server workers. Every worker on the host talks to them over a local TCP socket, so they can share state with no external infrastructure. Both are optional and off by default, and both require the WinterWebSwooleApplication runner.
Key-Value Store
Section titled “Key-Value Store”The KV store is a fast key-value store whose keys are grouped by a domain string. Any bean can use it by autowiring KvTemplate, and the SharedKvCache cache backend is built on it.
Enabling the KV Store
Section titled “Enabling the KV Store”Add the following block to your application.yml. The store will not start unless port is a positive integer.
winter: kv: port: 7880 # local TCP port the KV server listens on address: # optional bind address; defaults to 127.0.0.1 token: # optional shared secret; a random one is generated per startAutowiring KvTemplate
Section titled “Autowiring KvTemplate”Once the store is enabled, the framework registers a KvTemplate bean automatically. Inject it with #[Autowired]:
use dev\winterframework\io\kv\KvTemplate;use dev\winterframework\stereotype\Autowired;use dev\winterframework\stereotype\Service;
#[Service]class SessionCacheService {
#[Autowired] private KvTemplate $kvTemplate;
public function storeSession(string $userId, array $data): void { $this->kvTemplate->put('sessions', $userId, $data, ttl: 3600); }
public function loadSession(string $userId): mixed { return $this->kvTemplate->get('sessions', $userId); }}KvTemplate API Reference
Section titled “KvTemplate API Reference”| Method | Signature | Description |
|---|---|---|
put |
put(string $domain, string $key, mixed $data, int $ttl = 0): bool |
Store a value. $ttl is in seconds; 0 means no expiry. |
putIfNot |
putIfNot(string $domain, string $key, mixed $data, int $ttl = 0): bool |
Store only if the key does not already exist. |
get |
get(string $domain, string $key): mixed |
Retrieve a value, or null if absent. |
has |
has(string $domain, string $key): bool |
Check whether a key exists. |
del |
del(string $domain, string $key): bool |
Delete a single key. |
delAll |
delAll(string $domain): bool |
Delete every key in a domain. |
incr |
incr(string $domain, string $key, int|float|null $incVal = null): int|float |
Atomically increment a numeric value. |
decr |
decr(string $domain, string $key, int|float|null $decVal = null): int|float |
Atomically decrement a numeric value. |
getSet |
getSet(string $domain, string $key, mixed $value): mixed |
Set a new value and return the old one. |
getSetIfNot |
getSetIfNot(string $domain, string $key, mixed $data, int $ttl = 0): mixed |
Set a new value only if the key does not exist; returns the current value. |
append |
append(string $domain, string $key, string $append): int |
Append a string to an existing value; returns the new length. |
strLen |
strLen(string $domain, string $key): int |
Return the byte length of the stored string value. |
keys |
keys(string $domain, string $key): array |
Return matching keys (supports glob patterns). |
getAll |
getAll(string $domain): array |
Return all key→value pairs in a domain. |
stats |
stats(): array |
Return store statistics (connections, memory, etc.). |
ping |
ping(): int |
Health-check the store; returns latency in microseconds. |
Shared KV Cache
Section titled “Shared KV Cache”To use the KV store as a cache backend for #[Cacheable], register a CacheManager bean that wraps a SharedKvCache — see Caching.
Queue Store
Section titled “Queue Store”The queue store is a lightweight FIFO queue, addressed by queue name. Use it through QueueSharedTemplate to pass messages between workers on the same host. (#[Async] does not use it — async calls have their own shared-memory queue.)
Enabling the Queue Store
Section titled “Enabling the Queue Store”winter: queue: port: 7881 # local TCP port the queue server listens on address: # optional bind address; defaults to 127.0.0.1 token: # optional shared secret; a random one is generated per startAutowiring QueueSharedTemplate
Section titled “Autowiring QueueSharedTemplate”use dev\winterframework\io\queue\QueueSharedTemplate;use dev\winterframework\stereotype\Autowired;use dev\winterframework\stereotype\Service;
#[Service]class NotificationDispatcher {
#[Autowired] private QueueSharedTemplate $queue;
public function dispatch(string $userId, string $message): void { $this->queue->enqueue('notifications', [ 'userId' => $userId, 'message' => $message, ]); }
public function processNext(): mixed { return $this->queue->dequeue('notifications'); }}QueueSharedTemplate API Reference
Section titled “QueueSharedTemplate API Reference”| Method | Signature | Description |
|---|---|---|
enqueue |
enqueue(string $queue, mixed $data): bool |
Add an item to the tail of the named queue. |
dequeue |
dequeue(string $queue): mixed |
Remove and return the item at the head of the queue, or null if empty. |
size |
size(string $queue): int |
Return the number of items currently in the queue. |
delete |
delete(string $queue): bool |
Remove the entire named queue. |
stats |
stats(): array |
Return store statistics. |
ping |
ping(): int |
Health-check the store; returns latency in microseconds. |
Running Both Stores Together
Section titled “Running Both Stores Together”A typical application.yml that enables both stores side-by-side:
winter: kv: port: 7880 address: 127.0.0.1
queue: port: 7881 address: 127.0.0.1Both stores start as child processes before the HTTP workers, so they are ready when your beans initialize. You can verify connectivity by calling $kvTemplate->ping() or $queue->ping() inside an #[OnApplicationReady] listener.