RouteTableCache
in package
Route table cache: on a hit the router builds the whole `RouteList` from one Redis payload (no SQL).
Works like QueryCache: envelope {f, v, payload}, tag snapshot with
MGET before the database build, store with the old snapshot (a foreign commit plus bump
between the snapshot and SETEX makes the next read a miss, never stale).
Single global key app:cache:route:table. IMPORTANT: routing has no user context today; when
it gets a user or role dimension, the key must get it too, otherwise users share routes. The
table is a complete snapshot, so it also covers negative caching (an unknown slug or locale
is null without the database).
Independent of the master Config::$enabled: the router is switched on separately by
routerEnabled. No single-flight lock on purpose (one key, about 8 cheap queries per rebuild,
so a herd is negligible). Fail-open: the first PredisException turns the cache off for the
rest of the request.
Table of Contents
Constants
- FORMAT_VERSION : mixed = 1
- Payload format version; a mismatch is a miss (a safe bump when the shape changes). Independent of `QueryCache`.
- TAGS : mixed = [\App\UI\Api\System\Models\Entities\Route::clas...
- Invalidation tags (FQCNs of Api entities, shared with the query cache tag keys; the `BaseManager` decorator bumps them). `MGET` of 5 keys is still one round-trip.
- KEY_SUFFIX : mixed = 'route:table'
- STATS_SERVICE : mixed = 'RouteTable'
- Service dimension of the {@see CacheStats} counters (fail-open observability).
Properties
- $compression : CompressionHelper
- $config : Config
- $redis : ClientInterface
- $redisUnavailable : bool
- Per-request fail-open memo (the first `PredisException` turns the cache off).
- $stats : CacheStats|null
- $tagVersions : TagVersions
Methods
- __construct() : mixed
- clear() : void
- Manual brake: deletes the table key (fail-open).
- load() : RouteTableSnapshot
- Wraps the read of the route table. `$producer` is the database build ({@see \App\Core\Routers\RouteTableBuilder::build()}); it runs only on a miss or when the cache is off.
- jitteredTtl() : int
- Returns `routerTtl` with a ±10 % jitter ({@see TtlJitter}) against synchronized expiry.
- key() : string
- markUnavailable() : void
- readSnapshot() : RouteTableSnapshot|null
- Validates and deserializes the stored payload. Any invalidity is a miss.
- record() : void
- Records hit, miss and set counters in {@see CacheStats} (service dimension 'RouteTable'), fire-and-forget and fail-open (`CacheStats` swallows exceptions itself). Skipped when Redis is down.
- store() : void
Constants
FORMAT_VERSION
Payload format version; a mismatch is a miss (a safe bump when the shape changes). Independent of `QueryCache`.
public
mixed
FORMAT_VERSION
= 1
TAGS
Invalidation tags (FQCNs of Api entities, shared with the query cache tag keys; the `BaseManager` decorator bumps them). `MGET` of 5 keys is still one round-trip.
public
mixed
TAGS
= [\App\UI\Api\System\Models\Entities\Route::class, \App\UI\Api\System\Models\Entities\RouteText::class, \App\UI\Api\System\Models\Entities\Page::class, \App\UI\Api\System\Models\Entities\PageText::class, \App\UI\Api\System\Models\Entities\Localization::class]
KEY_SUFFIX
private
mixed
KEY_SUFFIX
= 'route:table'
STATS_SERVICE
Service dimension of the {@see CacheStats} counters (fail-open observability).
private
mixed
STATS_SERVICE
= 'RouteTable'
Properties
$compression read-only
private
CompressionHelper
$compression
$config read-only
private
Config
$config
$redis read-only
private
ClientInterface
$redis
$redisUnavailable
Per-request fail-open memo (the first `PredisException` turns the cache off).
private
bool
$redisUnavailable
= false
$stats read-only
private
CacheStats|null
$stats
= null
$tagVersions read-only
private
TagVersions
$tagVersions
Methods
__construct()
public
__construct(ClientInterface $redis, Config $config, TagVersions $tagVersions, CompressionHelper $compression[, CacheStats|null $stats = null ]) : mixed
Parameters
- $redis : ClientInterface
- $config : Config
- $tagVersions : TagVersions
- $compression : CompressionHelper
- $stats : CacheStats|null = null
clear()
Manual brake: deletes the table key (fail-open).
public
clear() : void
load()
Wraps the read of the route table. `$producer` is the database build ({@see \App\Core\Routers\RouteTableBuilder::build()}); it runs only on a miss or when the cache is off.
public
load(callable(): RouteTableSnapshot $producer) : RouteTableSnapshot
Parameters
- $producer : callable(): RouteTableSnapshot
Return values
RouteTableSnapshotjitteredTtl()
Returns `routerTtl` with a ±10 % jitter ({@see TtlJitter}) against synchronized expiry.
private
jitteredTtl() : int
Return values
intkey()
private
key() : string
Return values
stringmarkUnavailable()
private
markUnavailable() : void
readSnapshot()
Validates and deserializes the stored payload. Any invalidity is a miss.
private
readSnapshot(string|null $raw, array<string, int> $snapshot, bool &$invalidated) : RouteTableSnapshot|null
Parameters
- $raw : string|null
- $snapshot : array<string, int>
-
current tag snapshot
- $invalidated : bool
-
out parameter, true when the miss comes from a tag bump or format bump (not cold)
Return values
RouteTableSnapshot|nullrecord()
Records hit, miss and set counters in {@see CacheStats} (service dimension 'RouteTable'), fire-and-forget and fail-open (`CacheStats` swallows exceptions itself). Skipped when Redis is down.
private
record(array<string, int> $increments) : void
Parameters
- $increments : array<string, int>
store()
private
store(array<string, int>|null $snapshot, RouteTableSnapshot $table) : void
Parameters
- $snapshot : array<string, int>|null
- $table : RouteTableSnapshot