diff --git a/packages/core/src/idempotency.ts b/packages/core/src/idempotency.ts index e7034bc..3f6fa96 100644 --- a/packages/core/src/idempotency.ts +++ b/packages/core/src/idempotency.ts @@ -167,6 +167,12 @@ export class Idempotency { if (await this.isEnabled(reqInternal)) { const fingerPrint = this.getFingerPrint(reqInternal); const cacheKey = this.getIdempotencyCacheKey(reqInternal); + + if (res.error && req.options?.skipErrorsCache) { + // do not cache the error itself, clear the cache key and allow subsequent requests to retry + await this.storage.delete(cacheKey); + } + const payload: StoragePayload = { status: RequestStatusEnum.COMPLETE, fingerPrint, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 6478bef..2c49862 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -30,6 +30,12 @@ export interface IdempotencyOptions { * if set to `true` requests without idempotency key header will be rejected */ enforceIdempotency?: boolean; + /** + * @defaultValue `false` + * + * if set to `true` responses with errors will not be cached + */ + skipErrorsCache?: boolean; /** * @defaultValue `undefined` diff --git a/packages/storage-adapter-memory/src/adapter-memory.ts b/packages/storage-adapter-memory/src/adapter-memory.ts index e1af4b0..314499c 100644 --- a/packages/storage-adapter-memory/src/adapter-memory.ts +++ b/packages/storage-adapter-memory/src/adapter-memory.ts @@ -47,4 +47,8 @@ export class MemoryStorageAdapter implements StorageAdapter { } return val?.item; } + + async delete(key: string): Promise { + this.cache.delete(key); + } } diff --git a/packages/storage-adapter-redis/src/adapter-redis.ts b/packages/storage-adapter-redis/src/adapter-redis.ts index a9fe84e..7d00c10 100644 --- a/packages/storage-adapter-redis/src/adapter-redis.ts +++ b/packages/storage-adapter-redis/src/adapter-redis.ts @@ -50,4 +50,8 @@ export class RedisStorageAdapter implements StorageAdapter { const val = await this.client.get(key); return val ?? undefined; } + + async delete(key: string): Promise { + await this.client.del(key); + } } diff --git a/packages/storage/src/types.ts b/packages/storage/src/types.ts index f5888ca..4cf9e06 100644 --- a/packages/storage/src/types.ts +++ b/packages/storage/src/types.ts @@ -6,6 +6,7 @@ export interface StorageAdapter { ) => Promise; set: (key: string, val: string, { ttl }: { ttl?: number }) => Promise; get: (key: string) => Promise; + delete: (key: string) => Promise; connect?: () => Promise; disconnect?: () => Promise; }