@@ -5,25 +5,32 @@ import com.microsoft.azure.functions.annotation.FunctionName
5
5
import com.microsoft.azure.functions.annotation.QueueTrigger
6
6
import com.microsoft.azure.functions.annotation.StorageAccount
7
7
import gov.cdc.prime.reportstream.shared.QueueMessage
8
+ import gov.cdc.prime.reportstream.shared.Submission
8
9
import gov.cdc.prime.router.ActionLogger
9
10
import gov.cdc.prime.router.azure.ActionHistory
10
11
import gov.cdc.prime.router.azure.DataAccessTransaction
11
12
import gov.cdc.prime.router.azure.DatabaseAccess
12
13
import gov.cdc.prime.router.azure.QueueAccess
14
+ import gov.cdc.prime.router.azure.SubmissionTableService
13
15
import gov.cdc.prime.router.azure.WorkflowEngine
14
16
import gov.cdc.prime.router.azure.db.enums.TaskAction
17
+ import gov.cdc.prime.router.azure.observability.event.AzureEventService
18
+ import gov.cdc.prime.router.azure.observability.event.AzureEventServiceImpl
15
19
import gov.cdc.prime.router.azure.observability.event.ReportStreamEventName
16
20
import gov.cdc.prime.router.azure.observability.event.ReportStreamEventProperties
21
+ import gov.cdc.prime.router.azure.observability.event.ReportStreamEventService
17
22
import gov.cdc.prime.router.common.BaseEngine
18
23
import gov.cdc.prime.router.fhirengine.engine.FHIRConverter
19
24
import gov.cdc.prime.router.fhirengine.engine.FHIRDestinationFilter
20
25
import gov.cdc.prime.router.fhirengine.engine.FHIREngine
21
- import gov.cdc.prime.router.fhirengine.engine.FHIRReceiver
22
26
import gov.cdc.prime.router.fhirengine.engine.FHIRReceiverFilter
23
27
import gov.cdc.prime.router.fhirengine.engine.FHIRTranslator
24
- import gov.cdc.prime.router.fhirengine.engine.FhirReceiveQueueMessage
28
+ import gov.cdc.prime.router.fhirengine.engine.FhirConvertSubmissionQueueMessage
25
29
import gov.cdc.prime.router.fhirengine.engine.PrimeRouterQueueMessage
26
30
import gov.cdc.prime.router.fhirengine.engine.ReportPipelineMessage
31
+ import gov.cdc.prime.router.fhirengine.engine.SubmissionSenderNotFound
32
+ import gov.cdc.prime.router.history.db.ReportGraph
33
+ import gov.cdc.prime.router.report.ReportService
27
34
import org.apache.commons.lang3.StringUtils
28
35
import org.apache.logging.log4j.kotlin.Logging
29
36
import org.jooq.exception.DataAccessException
@@ -33,23 +40,41 @@ class FHIRFunctions(
33
40
private val actionLogger : ActionLogger = ActionLogger (),
34
41
private val databaseAccess : DatabaseAccess = BaseEngine .databaseAccessSingleton,
35
42
private val queueAccess : QueueAccess = QueueAccess ,
43
+ private val submissionTableService : SubmissionTableService = SubmissionTableService .getInstance(),
44
+ val reportService : ReportService = ReportService (ReportGraph (databaseAccess), databaseAccess),
45
+ val azureEventService : AzureEventService = AzureEventServiceImpl (),
46
+ val reportStreamEventService : ReportStreamEventService =
47
+ ReportStreamEventService (databaseAccess, azureEventService, reportService),
36
48
) : Logging {
37
49
38
50
/* *
39
51
* An azure function for ingesting and recording submissions
40
52
*/
41
- @FunctionName(" receive -fhir" )
53
+ @FunctionName(" convert-from-submissions -fhir" )
42
54
@StorageAccount(" AzureWebJobsStorage" )
43
- fun receive (
44
- @QueueTrigger(name = " message" , queueName = QueueMessage .elrReceiveQueueName )
55
+ fun convertFromSubmissions (
56
+ @QueueTrigger(name = " message" , queueName = QueueMessage .elrSubmissionConvertQueueName )
45
57
message : String ,
46
58
// Number of times this message has been dequeued
47
59
@BindingName(" DequeueCount" ) dequeueCount : Int = 1,
48
60
) {
49
61
logger.info(
50
- " message consumed from elr-fhir-receive queue"
62
+ " message consumed from ${ QueueMessage .elrSubmissionConvertQueueName} queue"
51
63
)
52
- process(message, dequeueCount, FHIRReceiver (), ActionHistory (TaskAction .receive))
64
+ process(
65
+ message,
66
+ dequeueCount,
67
+ FHIRConverter (reportStreamEventService = reportStreamEventService),
68
+ ActionHistory (TaskAction .convert)
69
+ )
70
+ val messageContent = readMessage(" convert" , message, dequeueCount)
71
+ val tableEntity = Submission (
72
+ messageContent.reportId.toString(),
73
+ " Accepted" ,
74
+ messageContent.blobURL,
75
+ actionLogger.errors.takeIf { it.isNotEmpty() }?.map { it.detail.message }?.toString()
76
+ )
77
+ submissionTableService.insertSubmission(tableEntity)
53
78
}
54
79
55
80
/* *
@@ -63,7 +88,12 @@ class FHIRFunctions(
63
88
// Number of times this message has been dequeued
64
89
@BindingName(" DequeueCount" ) dequeueCount : Int = 1,
65
90
) {
66
- process(message, dequeueCount, FHIRConverter (), ActionHistory (TaskAction .convert))
91
+ process(
92
+ message,
93
+ dequeueCount,
94
+ FHIRConverter (reportStreamEventService = reportStreamEventService),
95
+ ActionHistory (TaskAction .convert)
96
+ )
67
97
}
68
98
69
99
/* *
@@ -77,7 +107,12 @@ class FHIRFunctions(
77
107
// Number of times this message has been dequeued
78
108
@BindingName(" DequeueCount" ) dequeueCount : Int = 1,
79
109
) {
80
- process(message, dequeueCount, FHIRDestinationFilter (), ActionHistory (TaskAction .destination_filter))
110
+ process(
111
+ message,
112
+ dequeueCount,
113
+ FHIRDestinationFilter (reportStreamEventService = reportStreamEventService),
114
+ ActionHistory (TaskAction .destination_filter)
115
+ )
81
116
}
82
117
83
118
/* *
@@ -91,7 +126,12 @@ class FHIRFunctions(
91
126
// Number of times this message has been dequeued
92
127
@BindingName(" DequeueCount" ) dequeueCount : Int = 1,
93
128
) {
94
- process(message, dequeueCount, FHIRReceiverFilter (), ActionHistory (TaskAction .receiver_filter))
129
+ process(
130
+ message,
131
+ dequeueCount,
132
+ FHIRReceiverFilter (reportStreamEventService = reportStreamEventService),
133
+ ActionHistory (TaskAction .receiver_filter)
134
+ )
95
135
}
96
136
97
137
/* *
@@ -105,7 +145,12 @@ class FHIRFunctions(
105
145
// Number of times this message has been dequeued
106
146
@BindingName(" DequeueCount" ) dequeueCount : Int = 1,
107
147
) {
108
- process(message, dequeueCount, FHIRTranslator (), ActionHistory (TaskAction .translate))
148
+ process(
149
+ message,
150
+ dequeueCount,
151
+ FHIRTranslator (reportStreamEventService = reportStreamEventService),
152
+ ActionHistory (TaskAction .translate)
153
+ )
109
154
}
110
155
111
156
/* *
@@ -149,13 +194,27 @@ class FHIRFunctions(
149
194
recordResults(message, actionHistory, txn)
150
195
results
151
196
}
152
-
197
+ reportStreamEventService.sendQueuedEvents()
153
198
return newMessages
154
199
} catch (ex: DataAccessException ) {
155
200
// This is the one exception type that we currently will allow for retrying as there are occasional
156
201
// DB connectivity issues that are resolved without intervention
157
202
logger.error(ex)
158
203
throw ex
204
+ } catch (ex: SubmissionSenderNotFound ) {
205
+ // This is a specific error case that can occur while handling a report via the new Submission service
206
+ // In a situation that the sender is not found there is not enough information to record a report event
207
+ // and we want a poison queue message to be immediately added so that the configuration can be fixed
208
+ logger.error(ex)
209
+ val tableEntity = Submission (
210
+ ex.reportId.toString(),
211
+ " Rejected" ,
212
+ ex.blobURL,
213
+ actionLogger.errors.takeIf { it.isNotEmpty() }?.map { it.detail.message }?.toString()
214
+ )
215
+ submissionTableService.insertSubmission(tableEntity)
216
+ queueAccess.sendMessage(" ${messageContent.messageQueueName} -poison" , message)
217
+ return emptyList()
159
218
} catch (ex: Exception ) {
160
219
// We're catching anything else that occurs because the most likely cause is a code or configuration error
161
220
// that will not be resolved if the message is automatically retried
@@ -186,7 +245,7 @@ class FHIRFunctions(
186
245
187
246
return when (val queueMessage = QueueMessage .deserialize(message)) {
188
247
is QueueMessage .ReceiveQueueMessage -> {
189
- FhirReceiveQueueMessage (
248
+ FhirConvertSubmissionQueueMessage (
190
249
queueMessage.reportId,
191
250
queueMessage.blobURL,
192
251
queueMessage.digest,
0 commit comments