1- import { SQSBatchItemFailure , SQSEvent , SQSHandler } from "aws-lambda" ;
1+ import { Context , SQSBatchItemFailure , SQSEvent , SQSHandler } from "aws-lambda" ;
22import { $LetterRequestPreparedEvent } from "@nhsdigital/nhs-notify-event-schemas-letter-rendering-v1" ;
33import {
44 InsertLetter ,
@@ -11,6 +11,10 @@ import {
1111} from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/letter-events" ;
1212import { $LetterRequestPreparedEventV2 } from "@nhsdigital/nhs-notify-event-schemas-letter-rendering" ;
1313import { MetricsLogger , Unit , metricScope } from "aws-embedded-metrics" ;
14+ import {
15+ IdempotencyConfig ,
16+ makeIdempotent ,
17+ } from "@aws-lambda-powertools/idempotency" ;
1418import { Deps } from "../config/deps" ;
1519import {
1620 PreparedEvents ,
@@ -20,6 +24,10 @@ import {
2024 UpsertOperation ,
2125} from "./schemas" ;
2226
27+ const idempotencyConfig = new IdempotencyConfig ( {
28+ eventKeyJmesPath : "id" ,
29+ } ) ;
30+
2331function getOperationFromType ( type : string ) : UpsertOperation {
2432 if (
2533 type . startsWith ( "uk.nhs.notify.letter-rendering.letter-request.prepared" )
@@ -180,8 +188,13 @@ function parseQueueMessage(queueMessage: string): QueueMessage {
180188}
181189
182190export default function createUpsertLetterHandler ( deps : Deps ) : SQSHandler {
191+ const processRecordIdempotently = makeIdempotent ( processRecord , {
192+ persistenceStore : deps . idempotencyLayer ,
193+ config : idempotencyConfig ,
194+ } ) ;
195+
183196 return metricScope ( ( metrics : MetricsLogger ) => {
184- return async ( event : SQSEvent ) => {
197+ return async ( event : SQSEvent , context : Context ) => {
185198 const batchItemFailures : SQSBatchItemFailure [ ] = [ ] ;
186199 const perSupplierSuccess : Map < string , number > = new Map < string , number > ( ) ;
187200 const perSupplierFailure : Map < string , number > = new Map < string , number > ( ) ;
@@ -216,29 +229,13 @@ export default function createUpsertLetterHandler(deps: Deps): SQSHandler {
216229 supplier : supplierSpec ,
217230 } ) ;
218231
219- supplier =
220- ! supplierSpec || ! supplierSpec . supplierId
221- ? getSupplierIdFromEvent ( letterEvent )
222- : supplierSpec . supplierId ;
223-
224- const operation = getOperationFromType ( letterEvent . type ) ;
225-
226- await runUpsert (
227- operation ,
232+ idempotencyConfig . registerLambdaContext ( context ) ;
233+ supplier = await processRecordIdempotently (
228234 letterEvent ,
229- supplierSpec ?? {
230- supplierId : "unknown" ,
231- specId : "unknown" ,
232- priority : 10 ,
233- billingId : "unknown" ,
234- } ,
235+ supplierSpec ,
236+ perSupplierSuccess ,
235237 deps ,
236238 ) ;
237-
238- perSupplierSuccess . set (
239- supplier ,
240- ( perSupplierSuccess . get ( supplier ) || 0 ) + 1 ,
241- ) ;
242239 } catch ( error ) {
243240 deps . logger . error ( {
244241 description : "Error processing upsert of record" ,
@@ -261,3 +258,32 @@ export default function createUpsertLetterHandler(deps: Deps): SQSHandler {
261258 } ;
262259 } ) ;
263260}
261+
262+ async function processRecord (
263+ letterEvent : LetterStatusChangeEvent | PreparedEvents ,
264+ supplierSpec : SupplierSpec | undefined ,
265+ perSupplierSuccess : Map < string , number > ,
266+ deps : Deps ,
267+ ) {
268+ const supplier =
269+ ! supplierSpec || ! supplierSpec . supplierId
270+ ? getSupplierIdFromEvent ( letterEvent )
271+ : supplierSpec . supplierId ;
272+
273+ const operation = getOperationFromType ( letterEvent . type ) ;
274+
275+ await runUpsert (
276+ operation ,
277+ letterEvent ,
278+ supplierSpec ?? {
279+ supplierId : "unknown" ,
280+ specId : "unknown" ,
281+ priority : 10 ,
282+ billingId : "unknown" ,
283+ } ,
284+ deps ,
285+ ) ;
286+
287+ perSupplierSuccess . set ( supplier , ( perSupplierSuccess . get ( supplier ) || 0 ) + 1 ) ;
288+ return supplier ;
289+ }
0 commit comments