Skip to content

Commit 866837d

Browse files
author
Alexander Schueren
authored
feat(idempotency): preserve original error when wrapping into IdempotencyPersistenceLayerError (#1552)
* add cause field to persistance error * rename to error, to align with parameters package * add error cause to middleware
1 parent 12483a0 commit 866837d

14 files changed

+51
-27
lines changed

Diff for: packages/idempotency/src/IdempotencyHandler.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
IdempotencyInconsistentStateError,
66
IdempotencyItemAlreadyExistsError,
77
IdempotencyPersistenceLayerError,
8-
} from './Exceptions';
8+
} from './errors';
99
import { BasePersistenceLayer, IdempotencyRecord } from './persistence';
1010
import { IdempotencyConfig } from './IdempotencyConfig';
1111
import { MAX_RETRIES } from './constants';
@@ -80,7 +80,8 @@ export class IdempotencyHandler<U> {
8080
);
8181
} catch (e) {
8282
throw new IdempotencyPersistenceLayerError(
83-
'Failed to delete record from idempotency store'
83+
'Failed to delete record from idempotency store',
84+
e as Error
8485
);
8586
}
8687
throw e;
@@ -92,7 +93,8 @@ export class IdempotencyHandler<U> {
9293
);
9394
} catch (e) {
9495
throw new IdempotencyPersistenceLayerError(
95-
'Failed to update success record to idempotency store'
96+
'Failed to update success record to idempotency store',
97+
e as Error
9698
);
9799
}
98100

@@ -153,7 +155,10 @@ export class IdempotencyHandler<U> {
153155
idempotencyRecord
154156
) as U;
155157
} else {
156-
throw new IdempotencyPersistenceLayerError();
158+
throw new IdempotencyPersistenceLayerError(
159+
'Failed to save record in progress',
160+
e as Error
161+
);
157162
}
158163
}
159164

Diff for: packages/idempotency/src/Exceptions.ts renamed to packages/idempotency/src/errors.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,17 @@ class IdempotencyInconsistentStateError extends Error {}
3131
/**
3232
* Unrecoverable error from the data store
3333
*/
34-
class IdempotencyPersistenceLayerError extends Error {}
34+
class IdempotencyPersistenceLayerError extends Error {
35+
public readonly cause: Error | undefined;
36+
37+
public constructor(message: string, cause?: Error) {
38+
const errorMessage = cause
39+
? `${message}. This error was caused by: ${cause.message}.`
40+
: message;
41+
super(errorMessage);
42+
this.cause = cause;
43+
}
44+
}
3545

3646
/**
3747
* Payload does not contain an idempotent key

Diff for: packages/idempotency/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export * from './Exceptions';
1+
export * from './errors';
22
export * from './IdempotencyConfig';
33
export * from './idempotentDecorator';
44
export * from './makeFunctionIdempotent';

Diff for: packages/idempotency/src/middleware/makeHandlerIdempotent.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
IdempotencyInconsistentStateError,
66
IdempotencyItemAlreadyExistsError,
77
IdempotencyPersistenceLayerError,
8-
} from '../Exceptions';
8+
} from '../errors';
99
import { IdempotencyRecord } from '../persistence';
1010
import { MAX_RETRIES } from '../constants';
1111
import type {
@@ -124,7 +124,8 @@ const makeHandlerIdempotent = (
124124
}
125125
} else {
126126
throw new IdempotencyPersistenceLayerError(
127-
'Failed to save in progress record to idempotency store'
127+
'Failed to save in progress record to idempotency store',
128+
error as Error
128129
);
129130
}
130131
}
@@ -149,7 +150,8 @@ const makeHandlerIdempotent = (
149150
);
150151
} catch (e) {
151152
throw new IdempotencyPersistenceLayerError(
152-
'Failed to update success record to idempotency store'
153+
'Failed to update success record to idempotency store',
154+
e as Error
153155
);
154156
}
155157
};
@@ -172,7 +174,8 @@ const makeHandlerIdempotent = (
172174
);
173175
} catch (error) {
174176
throw new IdempotencyPersistenceLayerError(
175-
'Failed to delete record from idempotency store'
177+
'Failed to delete record from idempotency store',
178+
error as Error
176179
);
177180
}
178181
};

Diff for: packages/idempotency/src/persistence/BasePersistenceLayer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { BasePersistenceLayerInterface } from './BasePersistenceLayerInterface';
88
import {
99
IdempotencyItemAlreadyExistsError,
1010
IdempotencyValidationError,
11-
} from '../Exceptions';
11+
} from '../errors';
1212
import { LRUCache } from './LRUCache';
1313

1414
/**

Diff for: packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
IdempotencyItemAlreadyExistsError,
33
IdempotencyItemNotFoundError,
4-
} from '../Exceptions';
4+
} from '../errors';
55
import { IdempotencyRecordStatus } from '../types';
66
import type { DynamoPersistenceOptions } from '../types';
77
import {

Diff for: packages/idempotency/src/persistence/IdempotencyRecord.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { IdempotencyRecordOptions } from '../types';
22
import { IdempotencyRecordStatus } from '../types';
3-
import { IdempotencyInvalidStatusError } from '../Exceptions';
3+
import { IdempotencyInvalidStatusError } from '../errors';
44

55
/**
66
* Class representing an idempotency record.

Diff for: packages/idempotency/tests/unit/IdempotencyHandler.test.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
IdempotencyInconsistentStateError,
99
IdempotencyItemAlreadyExistsError,
1010
IdempotencyPersistenceLayerError,
11-
} from '../../src/Exceptions';
11+
} from '../../src/errors';
1212
import { IdempotencyRecordStatus } from '../../src/types';
1313
import { BasePersistenceLayer, IdempotencyRecord } from '../../src/persistence';
1414
import { IdempotencyHandler } from '../../src/IdempotencyHandler';
@@ -165,16 +165,20 @@ describe('Class IdempotencyHandler', () => {
165165
});
166166

167167
test('when persistences store throws any error, it wraps the error to IdempotencyPersistencesLayerError', async () => {
168+
const innerError = new Error('Some error');
168169
const mockSaveInProgress = jest
169170
.spyOn(mockIdempotencyOptions.persistenceStore, 'saveInProgress')
170-
.mockRejectedValue(new Error('Some error'));
171+
.mockRejectedValue(innerError);
171172
const mockDetermineResultFromIdempotencyRecord = jest
172173
.spyOn(IdempotencyHandler, 'determineResultFromIdempotencyRecord')
173174
.mockImplementation(() => 'result');
174-
175175
await expect(idempotentHandler.processIdempotency()).rejects.toThrow(
176-
IdempotencyPersistenceLayerError
176+
new IdempotencyPersistenceLayerError(
177+
'Failed to save record in progress',
178+
innerError
179+
)
177180
);
181+
178182
expect(mockSaveInProgress).toHaveBeenCalledTimes(1);
179183
expect(mockDetermineResultFromIdempotencyRecord).toHaveBeenCalledTimes(0);
180184
});
@@ -323,7 +327,9 @@ describe('Class IdempotencyHandler', () => {
323327
.mockRejectedValue(new Error('Some error'));
324328

325329
await expect(idempotentHandler.getFunctionResult()).rejects.toThrow(
326-
IdempotencyPersistenceLayerError
330+
new IdempotencyPersistenceLayerError(
331+
'Failed to delete record from idempotency store. This error was caused by: Some error.'
332+
)
327333
);
328334
expect(mockDeleteInProgress).toHaveBeenCalledTimes(1);
329335
});

Diff for: packages/idempotency/tests/unit/idempotentDecorator.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
IdempotencyInconsistentStateError,
1414
IdempotencyItemAlreadyExistsError,
1515
IdempotencyPersistenceLayerError,
16-
} from '../../src/Exceptions';
16+
} from '../../src/errors';
1717
import { IdempotencyConfig } from '../../src';
1818
import { Context } from 'aws-lambda';
1919
import { helloworldContext } from '@aws-lambda-powertools/commons/lib/samples/resources/contexts';

Diff for: packages/idempotency/tests/unit/makeFunctionIdempotent.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
IdempotencyInconsistentStateError,
1717
IdempotencyItemAlreadyExistsError,
1818
IdempotencyPersistenceLayerError,
19-
} from '../../src/Exceptions';
19+
} from '../../src/errors';
2020
import { IdempotencyConfig } from '../../src';
2121
import { Context } from 'aws-lambda';
2222

Diff for: packages/idempotency/tests/unit/makeHandlerIdempotent.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
IdempotencyInconsistentStateError,
1313
IdempotencyItemAlreadyExistsError,
1414
IdempotencyPersistenceLayerError,
15-
} from '../../src/Exceptions';
15+
} from '../../src/errors';
1616
import { IdempotencyConfig } from '../../src/';
1717
import middy from '@middy/core';
1818
import { MAX_RETRIES } from '../../src/constants';
@@ -115,7 +115,7 @@ describe('Middleware: makeHandlerIdempotent', () => {
115115
// Act && Assess
116116
await expect(handler(event, context)).rejects.toThrowError(
117117
new IdempotencyPersistenceLayerError(
118-
'Failed to save in progress record to idempotency store'
118+
'Failed to save in progress record to idempotency store. This error was caused by: Something went wrong.'
119119
)
120120
);
121121
});
@@ -131,7 +131,7 @@ describe('Middleware: makeHandlerIdempotent', () => {
131131
// Act && Assess
132132
await expect(handler(event, context)).rejects.toThrowError(
133133
new IdempotencyPersistenceLayerError(
134-
'Failed to update success record to idempotency store'
134+
'Failed to update success record to idempotency store. This error was caused by: Something went wrong.'
135135
)
136136
);
137137
});
@@ -149,7 +149,7 @@ describe('Middleware: makeHandlerIdempotent', () => {
149149
// Act && Assess
150150
await expect(handler(event, context)).rejects.toThrow(
151151
new IdempotencyPersistenceLayerError(
152-
'Failed to delete record from idempotency store'
152+
'Failed to delete record from idempotency store. This error was caused by: Something went wrong.'
153153
)
154154
);
155155
});

Diff for: packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import {
1313
IdempotencyItemAlreadyExistsError,
1414
IdempotencyValidationError,
15-
} from '../../../src/Exceptions';
15+
} from '../../../src/errors';
1616
import type { IdempotencyConfigOptions } from '../../../src/types';
1717
import { IdempotencyRecordStatus } from '../../../src/types';
1818

Diff for: packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { DynamoDBPersistenceLayer } from '../../../src/persistence/DynamoDBPersi
77
import {
88
IdempotencyItemAlreadyExistsError,
99
IdempotencyItemNotFoundError,
10-
} from '../../../src/Exceptions';
10+
} from '../../../src/errors';
1111
import { IdempotencyRecord } from '../../../src/persistence';
1212
import type { DynamoPersistenceOptions } from '../../../src/types';
1313
import { IdempotencyRecordStatus } from '../../../src/types';

Diff for: packages/idempotency/tests/unit/persistence/IdempotencyRecord.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* @group unit/idempotency/persistence/idempotencyRecord
55
*/
6-
import { IdempotencyInvalidStatusError } from '../../../src/Exceptions';
6+
import { IdempotencyInvalidStatusError } from '../../../src/errors';
77
import { IdempotencyRecord } from '../../../src/persistence';
88
import { IdempotencyRecordStatus } from '../../../src/types';
99

0 commit comments

Comments
 (0)