@@ -9,17 +9,15 @@ import type {
99 UploadToPdmOutcome ,
1010 UploadToPdmResult ,
1111} from 'app/upload-to-pdm' ;
12- import {
13- $TtlItemBusEvent ,
14- EventPublisher ,
15- Logger ,
16- PdmResourceRejectedEvent ,
17- PdmResourceSubmittedEvent ,
18- } from 'utils' ;
12+ import messageDownloadedValidator from 'digital-letters-events/MESHInboxMessageDownloaded.js' ;
13+ import pdmResourceSubmittedValidator from 'digital-letters-events/PDMResourceSubmitted.js' ;
14+ import pdmResourceSubmissionRejectedValidator from 'digital-letters-events/PDMResourceSubmissionRejected.js' ;
15+ import { MESHInboxMessageDownloaded } from 'digital-letters-events' ;
16+ import { EventPublisher , Logger } from 'utils' ;
1917
2018interface ProcessingResult {
2119 result : UploadToPdmResult ;
22- item ?: PdmResourceSubmittedEvent | PdmResourceRejectedEvent ;
20+ item ?: MESHInboxMessageDownloaded ;
2321}
2422
2523interface CreateHandlerDependencies {
@@ -35,29 +33,29 @@ async function processRecord(
3533 batchItemFailures : SQSBatchItemFailure [ ] ,
3634) : Promise < ProcessingResult > {
3735 try {
38- const {
39- data : item ,
40- error : parseError ,
41- success : parseSuccess ,
42- } = $TtlItemBusEvent . safeParse ( JSON . parse ( body ) ) ;
36+ const sqsEventBody = JSON . parse ( body ) ;
37+ const sqsEventDetail = sqsEventBody . detail ;
4338
44- if ( ! parseSuccess ) {
39+ const isEventValid = messageDownloadedValidator ( sqsEventDetail ) ;
40+ if ( ! isEventValid ) {
4541 logger . error ( {
46- err : parseError ,
42+ err : messageDownloadedValidator . errors ,
4743 description : 'Error parsing queue entry' ,
4844 } ) ;
4945 batchItemFailures . push ( { itemIdentifier : messageId } ) ;
50- return { result : { outcome : 'failed' } } ;
46+ return { result : { outcome : 'failed' } , item : sqsEventDetail } ;
5147 }
5248
53- const result = await uploadToPdm . send ( item . detail ) ;
49+ const messageDownloadedEvent : MESHInboxMessageDownloaded = sqsEventDetail ;
50+
51+ const result = await uploadToPdm . send ( messageDownloadedEvent ) ;
5452
5553 if ( result . outcome === 'failed' ) {
5654 batchItemFailures . push ( { itemIdentifier : messageId } ) ;
57- return { result : { outcome : 'failed' } , item : item . detail } ;
55+ return { result : { outcome : 'failed' } , item : sqsEventDetail } ;
5856 }
5957
60- return { result, item : item . detail } ;
58+ return { result, item : sqsEventDetail } ;
6159 } catch ( error ) {
6260 logger . error ( {
6361 err : error ,
@@ -68,44 +66,41 @@ async function processRecord(
6866 }
6967}
7068
69+ interface CategorizedResults {
70+ processed : Record < UploadToPdmOutcome | 'retrieved' , number > ;
71+ successfulItems : { event : MESHInboxMessageDownloaded ; resourceId : string } [ ] ;
72+ failedItems : MESHInboxMessageDownloaded [ ] ;
73+ }
74+
7175function categorizeResults (
7276 results : PromiseSettledResult < ProcessingResult > [ ] ,
73- successfulEvents : PdmResourceSubmittedEvent [ ] ,
74- failedEvents : PdmResourceRejectedEvent [ ] ,
7577 logger : Logger ,
76- ) : Record < UploadToPdmOutcome | 'retrieved' , number > {
78+ ) : CategorizedResults {
7779 const processed : Record < UploadToPdmOutcome | 'retrieved' , number > = {
7880 retrieved : results . length ,
7981 sent : 0 ,
8082 failed : 0 ,
8183 } ;
8284
85+ const successfulItems : {
86+ event : MESHInboxMessageDownloaded ;
87+ resourceId : string ;
88+ } [ ] = [ ] ;
89+ const failedItems : MESHInboxMessageDownloaded [ ] = [ ] ;
90+
8391 for ( const result of results ) {
8492 if ( result . status === 'fulfilled' ) {
8593 const { item, result : itemResult } = result . value ;
8694 processed [ itemResult . outcome ] += 1 ;
8795
8896 if ( item ) {
8997 if ( itemResult . outcome === 'sent' && itemResult . resourceId ) {
90- successfulEvents . push ( {
91- ...item ,
92- data : {
93- 'digital-letter-id' : item . data [ 'digital-letter-id' ] ,
94- messageReference : item . data . messageReference ,
95- senderId : item . data . senderId ,
96- resourceId : itemResult . resourceId ,
97- retryCount : 0 ,
98- } ,
98+ successfulItems . push ( {
99+ event : item ,
100+ resourceId : itemResult . resourceId ,
99101 } ) ;
100102 } else {
101- failedEvents . push ( {
102- ...item ,
103- data : {
104- 'digital-letter-id' : item . data [ 'digital-letter-id' ] ,
105- messageReference : item . data . messageReference ,
106- senderId : item . data . senderId ,
107- } ,
108- } ) ;
103+ failedItems . push ( item ) ;
109104 }
110105 }
111106 } else {
@@ -114,71 +109,89 @@ function categorizeResults(
114109 }
115110 }
116111
117- return processed ;
112+ return { processed, successfulItems , failedItems } ;
118113}
119114
120115async function publishSuccessfulEvents (
121- successfulEvents : PdmResourceSubmittedEvent [ ] ,
116+ successfulItems : { event : MESHInboxMessageDownloaded ; resourceId : string } [ ] ,
122117 eventPublisher : EventPublisher ,
123118 logger : Logger ,
124119) : Promise < void > {
125- if ( successfulEvents . length === 0 ) return ;
120+ if ( successfulItems . length === 0 ) return ;
126121
127122 try {
128123 const submittedFailedEvents = await eventPublisher . sendEvents (
129- successfulEvents . map ( ( event ) => ( {
124+ successfulItems . map ( ( { event, resourceId } ) => ( {
130125 ...event ,
131126 id : randomUUID ( ) ,
132127 time : new Date ( ) . toISOString ( ) ,
133128 recordedtime : new Date ( ) . toISOString ( ) ,
134129 type : 'uk.nhs.notify.digital.letters.pdm.resource.submitted.v1' ,
130+ dataschema :
131+ 'https://notify.nhs.uk/cloudevents/schemas/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submitted-data.schema.json' ,
132+ source : event . source . replace ( / \/ m e s h $ / , '/pdm' ) ,
133+ data : {
134+ messageReference : event . data . messageReference ,
135+ senderId : event . data . senderId ,
136+ resourceId,
137+ retryCount : - 1 , // Setting to -1 until this field is removed from pdm.resource.submitted.
138+ } ,
135139 } ) ) ,
140+ pdmResourceSubmittedValidator ,
136141 ) ;
137142 if ( submittedFailedEvents . length > 0 ) {
138143 logger . warn ( {
139144 description : 'Some successful events failed to publish' ,
140145 failedCount : submittedFailedEvents . length ,
141- totalAttempted : successfulEvents . length ,
146+ totalAttempted : successfulItems . length ,
142147 } ) ;
143148 }
144149 } catch ( error ) {
145150 logger . warn ( {
146151 err : error ,
147152 description : 'Failed to send successful events to EventBridge' ,
148- eventCount : successfulEvents . length ,
153+ eventCount : successfulItems . length ,
149154 } ) ;
150155 }
151156}
152157
153158async function publishFailedEvents (
154- failedEvents : PdmResourceRejectedEvent [ ] ,
159+ failedItems : MESHInboxMessageDownloaded [ ] ,
155160 eventPublisher : EventPublisher ,
156161 logger : Logger ,
157162) : Promise < void > {
158- if ( failedEvents . length === 0 ) return ;
163+ if ( failedItems . length === 0 ) return ;
159164
160165 try {
161166 const rejectedFailedEvents = await eventPublisher . sendEvents (
162- failedEvents . map ( ( event ) => ( {
167+ failedItems . map ( ( event ) => ( {
163168 ...event ,
164169 id : randomUUID ( ) ,
165170 time : new Date ( ) . toISOString ( ) ,
166171 recordedtime : new Date ( ) . toISOString ( ) ,
167172 type : 'uk.nhs.notify.digital.letters.pdm.resource.submission.rejected.v1' ,
173+ dataschema :
174+ 'https://notify.nhs.uk/cloudevents/schemas/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submission-rejected-data.schema.json' ,
175+ source : event . source . replace ( / \/ m e s h $ / , '/pdm' ) ,
176+ data : {
177+ messageReference : event . data . messageReference ,
178+ senderId : event . data . senderId ,
179+ } ,
168180 } ) ) ,
181+ pdmResourceSubmissionRejectedValidator ,
169182 ) ;
170183 if ( rejectedFailedEvents . length > 0 ) {
171184 logger . warn ( {
172185 description : 'Some failed events failed to publish' ,
173186 failedCount : rejectedFailedEvents . length ,
174- totalAttempted : failedEvents . length ,
187+ totalAttempted : failedItems . length ,
175188 } ) ;
176189 }
177190 } catch ( error ) {
178191 logger . warn ( {
179192 err : error ,
180193 description : 'Failed to send failed events to EventBridge' ,
181- eventCount : failedEvents . length ,
194+ eventCount : failedItems . length ,
182195 } ) ;
183196 }
184197}
@@ -190,23 +203,19 @@ export const createHandler = ({
190203} : CreateHandlerDependencies ) =>
191204 async function handler ( sqsEvent : SQSEvent ) : Promise < SQSBatchResponse > {
192205 const batchItemFailures : SQSBatchItemFailure [ ] = [ ] ;
193- const successfulEvents : PdmResourceSubmittedEvent [ ] = [ ] ;
194- const failedEvents : PdmResourceRejectedEvent [ ] = [ ] ;
195206
196207 const promises = sqsEvent . Records . map ( ( record ) =>
197208 processRecord ( record , uploadToPdm , logger , batchItemFailures ) ,
198209 ) ;
199210
200211 const results = await Promise . allSettled ( promises ) ;
201- const processed = categorizeResults (
212+ const { failedItems , processed, successfulItems } = categorizeResults (
202213 results ,
203- successfulEvents ,
204- failedEvents ,
205214 logger ,
206215 ) ;
207216
208- await publishSuccessfulEvents ( successfulEvents , eventPublisher , logger ) ;
209- await publishFailedEvents ( failedEvents , eventPublisher , logger ) ;
217+ await publishSuccessfulEvents ( successfulItems , eventPublisher , logger ) ;
218+ await publishFailedEvents ( failedItems , eventPublisher , logger ) ;
210219
211220 logger . info ( {
212221 description : 'Processed SQS Event.' ,
0 commit comments