Cluster Cache: Topology and Node Setup#
This page explains the runtime API and the exact pattern for adding the third, fourth, or Nth independently running application node.
Bootstrap one runtime per node#
Build the Node Cache configuration, Cluster configuration, and transport once
in your application’s service container or bootstrap. Keep the resulting
ClusterRuntime and inject either the runtime or its cache facade where
needed.
use Infocyph\CacheLayer\Cluster\ClusterCache;
use Infocyph\CacheLayer\Cluster\ClusterCacheConfig;
use Infocyph\CacheLayer\Node\NodeCacheConfig;
$runtime = ClusterCache::create(
node: new NodeCacheConfig(
sqliteFile: '/var/cache/catalog/node-cache.sqlite',
namespace: 'catalog',
lockDirectory: '/var/cache/catalog/locks',
),
cluster: new ClusterCacheConfig(
cluster: 'production',
nodeId: gethostname() ?: 'catalog-unknown-node',
),
transport: $transport,
);
$cache = $runtime->cache();
The returned runtime exposes this small coordination API:
Method |
Meaning |
|---|---|
|
The normal local Node Cache facade. |
|
Invalidate one key locally and publish an event. |
|
Invalidate one tag locally and publish an event. |
|
Clear the local namespace and publish an event. |
|
Publish one invalidation for each unique tag. |
|
Replay up to |
|
Perform retention-gap recovery; normally called by consume. |
|
Report cursor, transport, consume, and recovery health. |
The critical boundary is $runtime->cache(): all ordinary get(),
set(), remember(), delete(), and clear() calls are local
only. Use the runtime’s three invalidation methods when an operation must be
distributed.
Adding the third, fourth, or Nth node#
There is no central cluster object that receives a list of node instances and
no node-registration call. A cluster is formed when independently running
application nodes use the same cluster name and shared transport. Each
node creates its own runtime, local SQLite file, and consumer.
For example, this bootstrap function is deployed on every web/worker node. The
deployment supplies a different $nodeId on each machine or instance:
use Infocyph\CacheLayer\Cluster\ClusterCache;
use Infocyph\CacheLayer\Cluster\ClusterCacheConfig;
use Infocyph\CacheLayer\Cluster\ClusterRuntime;
use Infocyph\CacheLayer\Cluster\Transport\InvalidationTransportInterface;
use Infocyph\CacheLayer\Node\NodeCacheConfig;
function bootCatalogCluster(string $nodeId, InvalidationTransportInterface $transport): ClusterRuntime
{
return ClusterCache::create(
node: new NodeCacheConfig(
sqliteFile: "/var/cache/catalog/{$nodeId}.sqlite",
namespace: 'catalog',
),
cluster: new ClusterCacheConfig(
cluster: 'production-catalog', // identical on every node
nodeId: $nodeId, // unique on every node
),
transport: $transport, // points to one shared event store
);
}
$nodeOne = bootCatalogCluster('catalog-web-01', $transport);
$nodeTwo = bootCatalogCluster('catalog-web-02', $transport);
$nodeThree = bootCatalogCluster('catalog-web-03', $transport);
// Continue with any number of nodes.
In a real deployment these three calls run in separate processes/machines—not in one PHP request. Each process normally creates its own PDO connection to the same database or its own client connection to the selected transport.
The node-addition flow is:
Provision a private local cache directory/SQLite file for the new node.
Give it a unique
nodeIdwhile retaining the existing cluster name, namespace, and transport configuration.Start its consumer before or alongside application traffic.
The new node begins with no cursor, safely reads retained events, and then serves local cache reads/writes like every other node.
Existing nodes require no configuration change; they already publish into the common transport.
When node one executes $nodeOne->invalidateKey('product.42'), it invalidates
its own cache and publishes an event. Nodes two, three, and every later node
apply that event when their individual consumers next call consume().