redb.Route.Cache
4.7.2
Prefix Reserved
dotnet add package redb.Route.Cache --version 4.7.2
NuGet\Install-Package redb.Route.Cache -Version 4.7.2
<PackageReference Include="redb.Route.Cache" Version="4.7.2" />
<PackageVersion Include="redb.Route.Cache" Version="4.7.2" />
<PackageReference Include="redb.Route.Cache" />
paket add redb.Route.Cache --version 4.7.2
#r "nuget: redb.Route.Cache, 4.7.2"
#:package redb.Route.Cache@4.7.2
#addin nuget:?package=redb.Route.Cache&version=4.7.2
#tool nuget:?package=redb.Route.Cache&version=4.7.2
redb.Route.Cache
Cache as an EIP (WSO2 Cache mediator / Camel caffeine-cache analog) over the .NET caching
abstractions: IMemoryCache in-process (default, created on demand) or IDistributedCache
(Redis, SQL Server, anything registered in DI).
Caching scope
.Cache("customer-${header.customerId}", TimeSpan.FromMinutes(5))
.Enrich("http://crm/customers/${header.customerId}")
.EndCache()
On a hit the body (and, with .CacheHeaders(), the headers) comes from the cache and the inner
steps are skipped; on a miss they run and the result is stored. Header cache.hit tells which.
Options: .Region("customers"), .SlidingExpiration(...), .CacheHeaders(), .Distributed(),
.KeyFromBody().
The key, in C# and in <cache key>, is a template: ${...} holes are evaluated, and a key without one that starts with
no root of the message (header., property., body, exception., bean:, ref:, env:, a function call) is the key
as written, so orders-all and reports/daily are constants. A key that starts with a root is an expression
(header.customerId), and one that does not compile (header.a+b) fails when the route is built. A constant that
begins with a root word (body-cache, header.txt) is written in quotes: 'body-cache'.
.KeyFromBody() takes the SHA-256 of the body instead of an explicit key. Only the body is hashed: the
content type and the headers are not part of the key. A Stream body is read to the end for it and the
message continues with its bytes; an object goes through the context's data format for the message's
content type, the way the distributed cache stores it. A body that cannot be serialized fails the
exchange with an error that names KeyFromBody and the type.
Component
.To("cache:customers?action=get&key=${header.customerId}")
.Filter("header.cache.hit == false")
.Enrich("http://crm/...")
.To("cache:customers?action=put&key=${header.customerId}&ttl=5m")
.EndFilter()
cache:<region>?action=get|put|remove|clear&key=...&ttl=5m&sliding=1m&provider=memory|distributed&headers=X-Rate,Content-Language.
Durations: 500ms, 30s, 5m, 2h, 1d or hh:mm:ss (a bare number is refused: 5 would be five
days to TimeSpan; a number TimeSpan cannot hold is refused the same way). Region and key are joined
with a length-prefixed separator, so region a / key b:c and region a:b / key c are two entries.
getsetscache.hitand restores the entry where it was cached from: a reply the scope stored out ofOutcomes back asOut, anything else asIn.putstores the message as it reaches the step. The pipeline has folded the previous step's reply intoInby then. Of the headers it stores only the ones named withheaders=(see Headers).clearempties the region (see Boundaries for what it can see).- The options are checked when the endpoint is created, and
Tocreates it on the first message.
What a hit hands back
A miss is computed once per key at a time, across every cache node of the context that shares the
store: concurrent exchanges for the same key wait for the first one's result instead of each running
the inner steps. A failed computation is not cached, so the waiters retry one at a time. A Stream
body is buffered on the miss (the live message continues with the bytes) so a hit can replay it; a
JsonNode body is copied into and out of the cache. Text and byte arrays are treated as immutable.
Any other object (a POCO, a list) is shared by every hit by design: do not mutate what a cache
scope handed you, or clone it first.
Headers
A hit hands the entry to another exchange, so an entry never carries what an exchange came in with, and never a credential.
- Scope,
.CacheHeaders(). The entry keeps what the inner steps did to the headers, compared by instance with the ones the exchange came in with: the headers added or changed, and the names removed. A hit does the same to the current exchange and leaves its other headers alone,Authorization,Cookieand theredbHttp.*request metadata included. With the reply inOut, the reply's own headers and what the steps did toInare both kept. A header a step set to the very instance it arrived as counts as untouched. - Component,
put. Only the headers named withheaders=Name1,Name2; a name the message does not carry is skipped.cacheHeaders=trueis refused: aputsees the message as a whole and cannot tell the headers of the value from the headers of the request. - Never, in either form:
Authorization,Proxy-Authorization,Cookie,Set-Cookie. Naming one on aputis an error.
Setup
Nothing for the in-process cache. context.UseCache(o => o.MaxEntries = 10_000) / services.AddRedbRouteCache(o => ...)
register options (and the cache: component in DI). For Distributed, register an IDistributedCache
(services.AddStackExchangeRedisCache(...), AddDistributedMemoryCache(), or
context.AddService(typeof(IDistributedCache), cache)). A POCO body goes through the distributed cache
as JSON and comes back as the same CLR type wherever that type's assembly is loaded; where it is not,
the entry counts as a miss.
Boundaries
clearworks from a list of written keys, because neither abstraction can enumerate. On a distributed cache it removes the keys this process has written; a sliding key stays on the list for as long as it is read. On the in-process cache it removes the keys this context has written: two contexts sharing one hostIMemoryCachekeep a list each.- A value under a cache key that this package did not write is an error naming the key, not a hit
and not a miss: no envelope marker, not JSON, or an envelope version this build does not read. Give
the cache its own key prefix (
RedisCacheOptions.InstanceName) or another region. Entries written before the marker existed are refused the same way, so clear the regions of a distributed cache after upgrading. - One computation per key holds inside a context. Other processes, and other contexts in the same process, compute on their own: there is no distributed lock.
- Headers go through a distributed cache as JSON primitives; other values are dropped.
MaxEntriesbounds the cache the package creates; a cache registered by the host keeps its own settings.- No spans or metrics. A cache node is a call inside the process, not a transport.
cache.hitis the signal, inside the route.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- JsonPath.Net (>= 2.2.0)
- JsonSchema.Net (>= 7.3.4)
- Microsoft.Extensions.Caching.Memory (>= 10.0.13)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.13)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Options (>= 10.0.13)
- redb.Route (>= 4.7.2)
- redb.Route.Xml (>= 4.7.2)
-
net8.0
- JsonPath.Net (>= 2.2.0)
- JsonSchema.Net (>= 7.3.4)
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.13)
- Microsoft.Extensions.Caching.Memory (>= 10.0.13)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.13)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Options (>= 10.0.13)
- redb.Route (>= 4.7.2)
- redb.Route.Xml (>= 4.7.2)
-
net9.0
- JsonPath.Net (>= 2.2.0)
- JsonSchema.Net (>= 7.3.4)
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.13)
- Microsoft.Extensions.Caching.Memory (>= 10.0.13)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.13)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Options (>= 10.0.13)
- redb.Route (>= 4.7.2)
- redb.Route.Xml (>= 4.7.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.7.2 | 37 | 11/13/2026 |
| 4.7.1 | 50 | 11/11/2026 |
| 4.7.0 | 80 | 11/7/2026 |
| 4.6.2 | 83 | 11/5/2026 |
| 4.6.1 | 96 | 11/4/2026 |
| 4.6.0 | 98 | 11/3/2026 |
| 4.5.1 | 101 | 10/30/2026 |
| 4.5.0 | 98 | 10/29/2026 |
| 4.4.2 | 108 | 10/23/2026 |
| 4.4.1 | 124 | 10/21/2026 |
| 4.3.0 | 109 | 10/14/2026 |
| 4.2.3 | 97 | 10/8/2026 |
| 4.2.2 | 101 | 10/5/2026 |
| 4.2.0 | 111 | 9/30/2026 |
| 4.1.1 | 109 | 9/25/2026 |
| 4.1.0 | 107 | 9/21/2026 |
| 4.0.1 | 114 | 9/18/2026 |
| 4.0.0 | 117 | 9/11/2026 |