From ac2535810f9cb2dffde32d1605653b4405fbdf38 Mon Sep 17 00:00:00 2001 From: Kevin Secrist Date: Mon, 12 Feb 2024 17:55:13 -0500 Subject: [PATCH] feat(idempotency): return existing record in IdempotencyValidationError --- packages/idempotency/src/errors.ts | 9 ++++++++- .../src/persistence/BasePersistenceLayer.ts | 3 ++- .../persistence/BasePersistenceLayer.test.ts | 18 ++++++++++-------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/idempotency/src/errors.ts b/packages/idempotency/src/errors.ts index 674e05d6a6..1f40411083 100644 --- a/packages/idempotency/src/errors.ts +++ b/packages/idempotency/src/errors.ts @@ -30,7 +30,14 @@ class IdempotencyInvalidStatusError extends Error {} /** * Payload does not match stored idempotency record */ -class IdempotencyValidationError extends Error {} +class IdempotencyValidationError extends Error { + public existingRecord?: IdempotencyRecord; + + public constructor(message?: string, existingRecord?: IdempotencyRecord) { + super(message); + this.existingRecord = existingRecord; + } +} /** * State is inconsistent across multiple requests to persistence store diff --git a/packages/idempotency/src/persistence/BasePersistenceLayer.ts b/packages/idempotency/src/persistence/BasePersistenceLayer.ts index 108a7c0adf..f6eb24e2c4 100644 --- a/packages/idempotency/src/persistence/BasePersistenceLayer.ts +++ b/packages/idempotency/src/persistence/BasePersistenceLayer.ts @@ -319,7 +319,8 @@ abstract class BasePersistenceLayer implements BasePersistenceLayerInterface { const hashedPayload: string = this.getHashedPayload(data); if (hashedPayload !== record.payloadHash) { throw new IdempotencyValidationError( - 'Payload does not match stored record for this event key' + 'Payload does not match stored record for this event key', + record ); } } diff --git a/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts index b615434c9f..71f271706d 100644 --- a/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts @@ -243,18 +243,20 @@ describe('Class: BasePersistenceLayer', () => { payloadValidationJmesPath: 'foo', }), }); - jest.spyOn(persistenceLayer, '_getRecord').mockReturnValue( - new IdempotencyRecord({ - idempotencyKey: 'my-lambda-function#mocked-hash', - status: IdempotencyRecordStatus.INPROGRESS, - payloadHash: 'different-hash', - }) - ); + const existingRecord = new IdempotencyRecord({ + idempotencyKey: 'my-lambda-function#mocked-hash', + status: IdempotencyRecordStatus.INPROGRESS, + payloadHash: 'different-hash', + }); + jest + .spyOn(persistenceLayer, '_getRecord') + .mockReturnValue(existingRecord); // Act & Assess await expect(persistenceLayer.getRecord({ foo: 'bar' })).rejects.toThrow( new IdempotencyValidationError( - 'Payload does not match stored record for this event key' + 'Payload does not match stored record for this event key', + existingRecord ) ); });