DKNet

Reserve Redis keys and retain response values

Part of DKNet.AspCore.Idempotency.RedisStore. After provider registration, the filter uses the public core contract. This sample constructs the identity you would pass to that contract:

using DKNet.AspCore.Idempotency.Filtering;
var key = new IdempotentKeyInfo
{
    Scope = "user:demo", Method = "POST", Endpoint = "/ORDERS", IdempotentKey = "order-1"
};
Console.WriteLine(key.CompositeKey); // user:demo:POST:/ORDERS:order-1

The filter calls the Redis store, which atomically reserves and receives the previous value before the handler runs, then overwrites a cacheable completion.

The Redis key is CachePrefix followed directly by the lowercase SHA-256 hex digest of this identity. IsKeyProcessedAsync calls StringSetAndGetAsync with When.NotExists, reservation JSON and the reservation TTL. That is one atomic set-if-absent-and-return-previous operation, not GET followed by SET.

No previous value means this call reserved the key. A returned 102 sentinel means a duplicate still in flight; a completed record supplies the replay data. A logically expired record is deleted and the method recursively retries reservation. Invalid JSON propagates as a lookup error. Completion serializes CachedResponse and overwrites the key with StringSetAsync and the completed TTL.

⚙️ Configuration reference

The store reuses core options; the linked pages own their types and defaults.

Core setting Redis use
CachePrefix Prefix before the lowercase SHA-256 digest.
InFlightReservationTimeout TTL of the status-102 reservation.
Expiration TTL of the completed record.
JsonSerializerOptions Serialization of the stored record.

🧱 Where it fits

The package overview shows the host registrations and dependencies behind this capability. The core filter and selected store have separate responsibilities.

The consumer host selects this package’s components and supplies the runtime dependencies shown in the package architecture.

⚠️ Gotchas & limits