Skip to content

IIdempotencyStore

Namespace AgentPrism · Assembly AgentPrism.Abstractions.dll

The store for idempotency records.

public interface IIdempotencyStore

A request that carries an Idempotency-Key header is processed at most once, exactly as the HTTP Idempotency-Key standard (the pattern Stripe follows) prescribes: while the first request is running, a second request with the same key either gets the stored response, or (if still processing) gets 409.

The default (in-memory) setup registers the first-class InMemoryIdempotencyStore; it is sufficient for a single-instance deployment. A multi-instance deployment requires a SQL provider — otherwise each instance keeps its own key set and deduplication is lost across instances.

CompleteAsync(string, string, IdempotencyResponse, CancellationToken)

Section titled “ CompleteAsync(string, string, IdempotencyResponse, CancellationToken)”

Records the completed response and sets the key’s state to Completed.

ValueTask CompleteAsync(string tenantId, string key, IdempotencyResponse response, CancellationToken cancellationToken = default)

tenantId string

The tenant identifier.

key string

The key.

response IdempotencyResponse

The response to store.

cancellationToken CancellationToken

The cancellation token.

ValueTask

ReleaseAsync(string, string, CancellationToken)

Section titled “ ReleaseAsync(string, string, CancellationToken)”

Deletes the record after a failed request; a retry with the same key becomes free again.

ValueTask ReleaseAsync(string tenantId, string key, CancellationToken cancellationToken = default)

tenantId string

The tenant identifier.

key string

The key.

cancellationToken CancellationToken

The cancellation token.

ValueTask

A failed run’s record is not kept. The purpose of idempotency is to make retries safe; keeping a failure would mean the client can never retry after a transient error.

ReserveAsync(IdempotencyRequest, CancellationToken)

Section titled “ ReserveAsync(IdempotencyRequest, CancellationToken)”

Tries to reserve the key as Reserved. If the key already exists, the existing record’s state is returned and no new record is OPENED.

ValueTask<IdempotencyReservation> ReserveAsync(IdempotencyRequest request, CancellationToken cancellationToken = default)

request IdempotencyRequest

The reservation request.

cancellationToken CancellationToken

The cancellation token.

ValueTask<IdempotencyReservation>

The reservation result.

The reservation must be atomic: if two concurrent requests arrive with the same key, only one must get IdempotencyState.Reserved, the other IdempotencyState.InProgress.