Idempotency

IdempotentRequest Action Filter Attribute

The IdempotentRequest attribute is designed to ensure that a certain action is executed only once, regardless of the number of requests received. This is particularly useful for preventing duplicate processing in situations where the client might send the same request multiple times, intentionally or unintentionally.

Installation

You should install Eiffel.CrossCutting.Idempotency NuGet package into your application.

dotnet add package Eiffel.CrossCutting.Idempotency

This feature requires distributed caching, pelase visit Caching module.

Usage

To use this attribute, simply annotate the desired action method in your controller with

[IdempotentRequest]
public async Task PostAsync([FromBody] CreateBookingRequest request)
{
  .. // Your implementation details
}

Options

/// <summary>
/// Idempotency options
/// </summary>
public class IdempotencyOptions
{
    /// <summary>
    /// Header key identifier
    /// </summary>
    public string HeaderKeyIdentifier { get; set; } = "x-idempotency-key";

    /// <summary>
    /// Expire time
    /// </summary>
    public int ExpireTimeInSeconds { get; set; } = 0;

    /// <summary>
    /// Cache key prefix
    /// </summary>
    public string CacheKeyPrefix { get; set; } = "idempotency:{0}";

    /// <summary>
    /// Cache db index
    /// </summary>
    public int CacheDbIndex { get; set; } = 0;
}

The IdempotencyOptions class provides configurable options for the idempotency module. These options allow you to specify the behavior of idempotency checks in the system. HeaderKeyIdentifier: Specifies the name of the HTTP header used to uniquely identify a request for idempotency checks. ExpireTimeInSeconds: Sets the duration for which an idempotency record is retained in the cache. After this duration, the record is automatically removed, allowing a request with the same idempotency key to be processed again. The time is expressed in seconds. A value of 0 indicates that the records do not expire automatically. CacheKeyPrefix: Defines the format of the cache keys used to store idempotency records. The {0} placeholder is replaced with the actual idempotency key from the request. CacheDbIndex: Specifies the database index used when storing idempotency records in a Redis cache (or similar distributed cache that supports multiple databases). This allows you to separate idempotency records from other data in your cache.

Configuration This class is typically used in the Startup configuration method where it is registered with the dependency injection system and its properties are set based on configuration file values or hardcoded settings. After being registered, the options are used by the idempotency middleware or action filter to determine the behavior of idempotency checks.

The IdempotencyOptions configuration is optional; if not specified, the system will use the default values.

// Program.cs (.NET5 and above)
public static async Task Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.Configure<IdempotencyOptions>(options =>
    {
        options.HeaderKeyIdentifier = "X-Request-Id";
        options.ExpireTimeInSeconds = 3600;
        options.CacheKeyPrefix = "customPrefix:{0}";
        options.CacheDbIndex = 1;
    });
 
    var app = builder.Build();
    app.Run();
}

Last updated