Dapr cache
The Dapr kind stores the values in a Dapr state store.
Dapr talks to many backends (Redis, PostgreSQL, Azure Cosmos DB and others), so the choice of the store moves out of your
application and into a Dapr component file. This page extends the caching guide.
What it solves
DaprCache (DaprCache) is an ICache on top of the DaprClient of the Dapr.Client package.
It exposes a state store as a named Arc4u cache, next to caches of the other kinds.
Compared with the other kinds:
- Values are serialized by the Dapr client (System.Text.Json), not by an IObjectSerialization.
There is no
SerializerName, and you do not need to register a serializer for this kind. - A sliding expiration is not supported:
PutwithisSlided: truethrowsNotSupportedException. - Expiration is the
ttlInSecondsmetadata of the state store, so the state store must support time to live.
Packages involved
| Package | Use it for |
|---|---|
Arc4u.Caching.Dapr |
DaprCache (kind Dapr) and AddDaprCacheKind(). References Dapr.Client. |
Arc4u.Caching |
ICacheContext and AddCacheContext. |
Install
dotnet add package Arc4u.Caching.Dapr --prerelease
The application must run with a Dapr sidecar (dapr run, or the Dapr annotations on Kubernetes) and a state store component
whose metadata.name is the value you put in Settings:Name. The DaprClient finds the sidecar with the
DAPR_HTTP_PORT and DAPR_GRPC_PORT environment variables that the sidecar sets.
Configuration
appsettings.json
{
"Caching": {
"Default": "Sidecar",
"Caches": [
{
"Name": "Sidecar",
"Kind": "Dapr",
"IsAutoStart": true,
"Settings": {
"Name": "statestore"
}
}
]
}
}
The settings bind to DaprCacheOption:
| Key | Type | Default | Description |
|---|---|---|---|
Caching:Caches:n:Settings:Name |
string |
empty | Name of the Dapr state store component, as in the metadata.name of its YAML file. Required in practice: an empty name makes every operation fail. |
The state store component is Dapr configuration, not Arc4u configuration. A minimal file for a local test, using the in-memory state store of Dapr:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.in-memory
version: v1
Use a persistent store, such as state.redis, in production. See the
Dapr state store reference.
Code
// Program.cs
using Arc4u.Caching;
using Arc4u.Caching.Dapr;
using Arc4u.Dependency;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddILogger();
builder.Services.AddCacheContext(builder.Configuration);
builder.Services.AddDaprCacheKind();
var app = builder.Build();
app.Run();
Common scenarios
Native AOT and trimming
The Dapr client serializes with its default options, which use reflection. In a trimmed or native AOT application, give it
options whose TypeInfoResolver is a JsonSerializerContext declaring the types you put in the cache. The name of the cache
(Shared below) is the Name of the entry in Caching:Caches; the store name still comes from the configuration.
// Program.cs
using System.Text.Json;
using System.Text.Json.Serialization;
using Arc4u.Configuration.Dapr;
builder.Services.Configure<DaprCacheOption>("Shared", o =>
o.JsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) { TypeInfoResolver = AppJsonContext.Default });
[JsonSerializable(typeof(Report))]
internal sealed partial class AppJsonContext : JsonSerializerContext;
Keep JsonSerializerDefaults.Web to read values saved with the default options. A type that is not in the context throws a
DataCacheException whose inner exception is a NotSupportedException.
Expire a value
using Arc4u.Caching;
public static class DaprExpiration
{
public static Task RunAsync(ICache cache)
{
// Absolute expiration only: the ttlInSeconds metadata is sent to the state store.
return cache.PutAsync("report", TimeSpan.FromMinutes(5), "value");
}
}
Extensibility points
AddDaprCacheKind() registers DaprCache under the key Dapr with TryAddKeyedTransient. To replace it, register your own ICache
under that key before calling it, or instead of it.
Troubleshooting
Operations fail to connect
No sidecar is reachable. Start the application with dapr run, or check the DAPR_HTTP_PORT and DAPR_GRPC_PORT variables.
The initialization creates the client but does not contact the sidecar, so the error appears on the first operation.
DataCacheException on Get or Put
The Dapr client failed; its exception is the InnerException. The synchronous methods wait for the asynchronous Dapr calls,
so prefer GetAsync and PutAsync in a web application.
See also
- Caching
- Serialization
- Arc4u.Caching.Dapr in the API reference