Skip to content

Commit f8e1f11

Browse files
authored
Merge pull request #884 from Project-MONAI/nds-externalAppPayload
Nds external app payload
2 parents a4c63ac + b44a423 commit f8e1f11

File tree

10 files changed

+78
-36
lines changed

10 files changed

+78
-36
lines changed

src/Common/Configuration/WorkflowManagerOptions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public class WorkflowManagerOptions : PagedOptions
7272
public string DicomTagsDisallowed { get; set; } = string.Empty;
7373

7474
[ConfigurationKeyName("migExternalAppPlugins")]
75-
public List<string> MigExternalAppPlugins { get; set; }
75+
public string[] MigExternalAppPlugins { get; set; }
7676

7777
public WorkflowManagerOptions()
7878
{

src/WorkflowManager/Logging/Log.200000.Workflow.cs

+3
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,8 @@ public static partial class Log
102102

103103
[LoggerMessage(EventId = 210006, Level = LogLevel.Information, Message = "Attached PatientMetadata {metadata}.")]
104104
public static partial void AttachedPatientMetadataToTaskExec(this ILogger logger, string metadata);
105+
106+
[LoggerMessage(EventId = 210007, Level = LogLevel.Information, Message = "Exporting to MIG task Id {taskid}, export destination {destination} number of files {fileCount} Mig data plugins {plugins}.")]
107+
public static partial void LogMigExport(this ILogger logger, string taskid, string destination, int fileCount, string plugins);
105108
}
106109
}

src/WorkflowManager/Logging/Log.500000.Messaging.cs

+3
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,8 @@ public static partial class Log
7070

7171
[LoggerMessage(EventId = 500016, Level = LogLevel.Debug, Message = "Export complete message received.")]
7272
public static partial void ExportCompleteReceived(this ILogger logger);
73+
74+
[LoggerMessage(EventId = 200017, Level = LogLevel.Debug, Message = "Workflow continuation event so not creating payload.")]
75+
public static partial void WorkflowContinuation(this ILogger logger);
7376
}
7477
}

src/WorkflowManager/PayloadListener/Services/EventPayloadRecieverService.cs

+19-11
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,29 @@ public async Task ReceiveWorkflowPayload(MessageReceivedEventArgs message)
7373
return;
7474
}
7575

76-
var payload = await PayloadService.CreateAsync(requestEvent);
77-
if (payload is null)
76+
if (string.IsNullOrWhiteSpace(requestEvent.WorkflowInstanceId) || string.IsNullOrWhiteSpace(requestEvent.TaskId))
7877
{
79-
Logger.WorkflowRequestRequeuePayloadCreateError(message.Message.MessageId);
80-
await _messageSubscriber.RequeueWithDelay(message.Message);
8178

82-
return;
83-
}
79+
var payload = await PayloadService.CreateAsync(requestEvent);
80+
if (payload is null)
81+
{
82+
Logger.WorkflowRequestRequeuePayloadCreateError(message.Message.MessageId);
83+
await _messageSubscriber.RequeueWithDelay(message.Message);
8484

85-
if (!await WorkflowExecuterService.ProcessPayload(requestEvent, payload))
86-
{
87-
Logger.WorkflowRequestRequeuePayloadProcessError(message.Message.MessageId);
88-
await _messageSubscriber.RequeueWithDelay(message.Message);
85+
return;
86+
}
8987

90-
return;
88+
if (!await WorkflowExecuterService.ProcessPayload(requestEvent, payload))
89+
{
90+
Logger.WorkflowRequestRequeuePayloadProcessError(message.Message.MessageId);
91+
await _messageSubscriber.RequeueWithDelay(message.Message);
92+
93+
return;
94+
}
95+
}
96+
else
97+
{
98+
Logger.WorkflowContinuation();
9199
}
92100

93101
_messageSubscriber.Acknowledge(message.Message);

src/WorkflowManager/PayloadListener/Services/PayloadListenerService.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ private void SetupPolling()
104104
_logger.EventSubscription(ServiceName, TaskStatusUpdateRoutingKey);
105105

106106
_messageSubscriber.SubscribeAsync(ExportCompleteRoutingKey, ExportCompleteRoutingKey, OnExportCompleteReceivedCallback);
107-
_logger.EventSubscription(ServiceName, ExportCompleteRoutingKey); }
107+
_logger.EventSubscription(ServiceName, ExportCompleteRoutingKey);
108+
}
108109
private async Task OnWorkflowRequestReceivedCallbackAsync(MessageReceivedEventArgs eventArgs)
109110
{
110111

src/WorkflowManager/WorkflowExecuter/Services/WorkflowExecuterService.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public WorkflowExecuterService(
8989
_defaultPerTaskTypeTimeoutMinutes = configuration.Value.PerTaskTypeTimeoutMinutes;
9090
TaskDispatchRoutingKey = configuration.Value.Messaging.Topics.TaskDispatchRequest;
9191
TaskTimeoutRoutingKey = configuration.Value.Messaging.Topics.AideClinicalReviewCancelation;
92-
_migExternalAppPlugins = configuration.Value.MigExternalAppPlugins;
92+
_migExternalAppPlugins = configuration.Value.MigExternalAppPlugins.ToList();
9393
ExportRequestRoutingKey = $"{configuration.Value.Messaging.Topics.ExportRequestPrefix}.{configuration.Value.Messaging.DicomAgents.ScuAgentName}";
9494

9595
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -482,6 +482,7 @@ private async Task<bool> UpdateWorkflowInstanceStatus(WorkflowInstance workflowI
482482

483483
return true;
484484
}
485+
485486
private async Task HandleExternalAppAsync(WorkflowRevision workflow, WorkflowInstance workflowInstance, TaskExecution task, string correlationId)
486487
{
487488
var plugins = _migExternalAppPlugins;
@@ -524,7 +525,6 @@ private async Task HandleDicomExportAsync(WorkflowRevision workflow, WorkflowIns
524525

525526
return;
526527
}
527-
528528
await DispatchDicomExport(workflowInstance, task, exportList, artifactValues, correlationId, plugins);
529529
}
530530

@@ -563,6 +563,7 @@ private async Task<bool> DispatchDicomExport(WorkflowInstance workflowInstance,
563563
return false;
564564
}
565565

566+
_logger.LogMigExport(task.TaskId, string.Join(",", exportDestinations), artifactValues.Length, string.Join(",", plugins));
566567
await ExportRequest(workflowInstance, task, exportDestinations, artifactValues, correlationId, plugins);
567568
return await _workflowInstanceRepository.UpdateTaskStatusAsync(workflowInstance.Id, task.TaskId, TaskExecutionStatus.Dispatched);
568569
}
@@ -812,6 +813,7 @@ private async Task<bool> TimeOutEvent(WorkflowInstance workflowInstance, TaskExe
812813
var exportRequestEvent = EventMapper.GenerateTaskCancellationEvent("", taskExec.ExecutionId, workflowInstance.Id, taskExec.TaskId, FailureReason.TimedOut, "Timed out");
813814
var jsonMesssage = new JsonMessage<TaskCancellationEvent>(exportRequestEvent, MessageBrokerConfiguration.WorkflowManagerApplicationId, correlationId, Guid.NewGuid().ToString());
814815

816+
_logger.TaskTimedOut(taskExec.TaskId, workflowInstance.Id, taskExec.Timeout);
815817
await _messageBrokerPublisherService.Publish(TaskTimeoutRoutingKey, jsonMesssage.ToMessage());
816818
return true;
817819
}

src/WorkflowManager/WorkflowManager/appsettings.Local.json

+21-18
Original file line numberDiff line numberDiff line change
@@ -96,22 +96,25 @@
9696
"scuAgentName": "monaiscu"
9797
}
9898
},
99-
"dicomTagsDisallowed": "PatientName,PatientID,IssuerOfPatientID,TypeOfPatientID,IssuerOfPatientIDQualifiersSequence,SourcePatientGroupIdentificationSequence,GroupOfPatientsIdentificationSequence,SubjectRelativePositionInImage,PatientBirthDate,PatientBirthTime,PatientBirthDateInAlternativeCalendar,PatientDeathDateInAlternativeCalendar,PatientAlternativeCalendar,PatientSex,PatientInsurancePlanCodeSequence,PatientPrimaryLanguageCodeSequence,PatientPrimaryLanguageModifierCodeSequence,QualityControlSubject,QualityControlSubjectTypeCodeSequence,StrainDescription,StrainNomenclature,StrainStockNumber,StrainSourceRegistryCodeSequence,StrainStockSequence,StrainSource,StrainAdditionalInformation,StrainCodeSequence,GeneticModificationsSequence,GeneticModificationsDescription,GeneticModificationsNomenclature,GeneticModificationsCodeSequence,OtherPatientIDsRETIRED,OtherPatientNames,OtherPatientIDsSequence,PatientBirthName,PatientAge,PatientSize,PatientSizeCodeSequence,PatientBodyMassIndex,MeasuredAPDimension,MeasuredLateralDimension,PatientWeight,PatientAddress,InsurancePlanIdentificationRETIRED,PatientMotherBirthName,MilitaryRank,BranchOfService,MedicalRecordLocatorRETIRED,ReferencedPatientPhotoSequence,MedicalAlerts,Allergies,CountryOfResidence,RegionOfResidence,PatientTelephoneNumbers,PatientTelecomInformation,EthnicGroup,Occupation,SmokingStatus,AdditionalPatientHistory,PregnancyStatus,LastMenstrualDate,PatientReligiousPreference,PatientSpeciesDescription,PatientSpeciesCodeSequence,PatientSexNeutered,AnatomicalOrientationType,PatientBreedDescription,PatientBreedCodeSequence,BreedRegistrationSequence,BreedRegistrationNumber,BreedRegistryCodeSequence,ResponsiblePerson,ResponsiblePersonRole,ResponsibleOrganization,PatientComments,ExaminedBodyThickness"
100-
},
101-
"InformaticsGateway": {
102-
"apiHost": "http://localhost:5010",
103-
"username": "aide",
104-
"password": "example"
105-
},
106-
"Kestrel": {
107-
"EndPoints": {
108-
"Http": {
109-
"Url": "http://localhost:5000"
110-
}
99+
"dicomTagsDisallowed": "PatientName,PatientID,IssuerOfPatientID,TypeOfPatientID,IssuerOfPatientIDQualifiersSequence,SourcePatientGroupIdentificationSequence,GroupOfPatientsIdentificationSequence,SubjectRelativePositionInImage,PatientBirthDate,PatientBirthTime,PatientBirthDateInAlternativeCalendar,PatientDeathDateInAlternativeCalendar,PatientAlternativeCalendar,PatientSex,PatientInsurancePlanCodeSequence,PatientPrimaryLanguageCodeSequence,PatientPrimaryLanguageModifierCodeSequence,QualityControlSubject,QualityControlSubjectTypeCodeSequence,StrainDescription,StrainNomenclature,StrainStockNumber,StrainSourceRegistryCodeSequence,StrainStockSequence,StrainSource,StrainAdditionalInformation,StrainCodeSequence,GeneticModificationsSequence,GeneticModificationsDescription,GeneticModificationsNomenclature,GeneticModificationsCodeSequence,OtherPatientIDsRETIRED,OtherPatientNames,OtherPatientIDsSequence,PatientBirthName,PatientAge,PatientSize,PatientSizeCodeSequence,PatientBodyMassIndex,MeasuredAPDimension,MeasuredLateralDimension,PatientWeight,PatientAddress,InsurancePlanIdentificationRETIRED,PatientMotherBirthName,MilitaryRank,BranchOfService,MedicalRecordLocatorRETIRED,ReferencedPatientPhotoSequence,MedicalAlerts,Allergies,CountryOfResidence,RegionOfResidence,PatientTelephoneNumbers,PatientTelecomInformation,EthnicGroup,Occupation,SmokingStatus,AdditionalPatientHistory,PregnancyStatus,LastMenstrualDate,PatientReligiousPreference,PatientSpeciesDescription,PatientSpeciesCodeSequence,PatientSexNeutered,AnatomicalOrientationType,PatientBreedDescription,PatientBreedCodeSequence,BreedRegistrationSequence,BreedRegistrationNumber,BreedRegistryCodeSequence,ResponsiblePerson,ResponsiblePersonRole,ResponsibleOrganization,PatientComments,ExaminedBodyThickness",
100+
"migExternalAppPlugins": [
101+
"Monai.Deploy.InformaticsGateway.PlugIns.RemoteAppExecution.DicomDeidentifier, Monai.Deploy.InformaticsGateway.PlugIns.RemoteAppExecution, Version=0.0.0.0"
102+
],
103+
"InformaticsGateway": {
104+
"apiHost": "http://localhost:5010",
105+
"username": "aide",
106+
"password": "example"
111107
},
112-
"LogHttpRequestQuery": false,
113-
"LogHttpRequestBody": false,
114-
"LogHttpResponseBody": true
115-
},
116-
"AllowedHosts": "*"
117-
}
108+
"Kestrel": {
109+
"EndPoints": {
110+
"Http": {
111+
"Url": "http://localhost:5000"
112+
}
113+
},
114+
"LogHttpRequestQuery": false,
115+
"LogHttpRequestBody": false,
116+
"LogHttpResponseBody": true
117+
},
118+
"AllowedHosts": "*"
119+
}
120+
}

src/WorkflowManager/WorkflowManager/appsettings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
}
103103
},
104104
"dicomTagsDisallowed": "PatientName,PatientID,IssuerOfPatientID,TypeOfPatientID,IssuerOfPatientIDQualifiersSequence,SourcePatientGroupIdentificationSequence,GroupOfPatientsIdentificationSequence,SubjectRelativePositionInImage,PatientBirthDate,PatientBirthTime,PatientBirthDateInAlternativeCalendar,PatientDeathDateInAlternativeCalendar,PatientAlternativeCalendar,PatientSex,PatientInsurancePlanCodeSequence,PatientPrimaryLanguageCodeSequence,PatientPrimaryLanguageModifierCodeSequence,QualityControlSubject,QualityControlSubjectTypeCodeSequence,StrainDescription,StrainNomenclature,StrainStockNumber,StrainSourceRegistryCodeSequence,StrainStockSequence,StrainSource,StrainAdditionalInformation,StrainCodeSequence,GeneticModificationsSequence,GeneticModificationsDescription,GeneticModificationsNomenclature,GeneticModificationsCodeSequence,OtherPatientIDsRETIRED,OtherPatientNames,OtherPatientIDsSequence,PatientBirthName,PatientAge,PatientSize,PatientSizeCodeSequence,PatientBodyMassIndex,MeasuredAPDimension,MeasuredLateralDimension,PatientWeight,PatientAddress,InsurancePlanIdentificationRETIRED,PatientMotherBirthName,MilitaryRank,BranchOfService,MedicalRecordLocatorRETIRED,ReferencedPatientPhotoSequence,MedicalAlerts,Allergies,CountryOfResidence,RegionOfResidence,PatientTelephoneNumbers,PatientTelecomInformation,EthnicGroup,Occupation,SmokingStatus,AdditionalPatientHistory,PregnancyStatus,LastMenstrualDate,PatientReligiousPreference,PatientSpeciesDescription,PatientSpeciesCodeSequence,PatientSexNeutered,AnatomicalOrientationType,PatientBreedDescription,PatientBreedCodeSequence,BreedRegistrationSequence,BreedRegistrationNumber,BreedRegistryCodeSequence,ResponsiblePerson,ResponsiblePersonRole,ResponsibleOrganization,PatientComments,ExaminedBodyThickness",
105-
"migExternalAppPlugins": "Monai.Deploy.InformaticsGateway.ExecutionPlugins.ExternalAppOutgoing, Monai.Deploy.InformaticsGateway, Version=0.0.0.0"
105+
"migExternalAppPlugins": [ "Monai.Deploy.InformaticsGateway.PlugIns.RemoteAppExecution.DicomDeidentifier, Monai.Deploy.InformaticsGateway.PlugIns.RemoteAppExecution, Version=0.0.0.0" ]
106106
},
107107
"InformaticsGateway": {
108108
"apiHost": "http://localhost:5010",

tests/UnitTests/PayloadListener.Tests/Services/EventPayloadRecieverServiceTests.cs

+22
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,28 @@ public void ExportCompletePayload_ErrorIsThrown_MessageIsRejectedAndRequeued()
276276
_mockMessageBrokerSubscriberService.VerifyNoOtherCalls();
277277
}
278278

279+
[Test]
280+
public void ReceiveWorkflowPayload_With_WorkflowId_And_TaskID()
281+
{
282+
283+
var exportRequestMessage = new WorkflowRequestEvent
284+
{
285+
CorrelationId = Guid.NewGuid().ToString(),
286+
WorkflowInstanceId = Guid.NewGuid().ToString(),
287+
TaskId = "exporttask"
288+
};
289+
var jsonMessage = new JsonMessage<WorkflowRequestEvent>(exportRequestMessage, MessageBrokerConfiguration.WorkflowManagerApplicationId, exportRequestMessage.CorrelationId);
290+
var message = new MessageReceivedEventArgs(jsonMessage.ToMessage(), CancellationToken.None);
291+
292+
_mockEventPayloadValidator.Setup(p => p.ValidateWorkflowRequest(It.IsAny<WorkflowRequestEvent>())).Returns(true);
293+
294+
_workflowExecuterService.Setup(p => p.ProcessPayload(It.IsAny<WorkflowRequestEvent>(), It.IsAny<Payload>())).ReturnsAsync(true);
295+
296+
_eventPayloadReceiverService.ReceiveWorkflowPayload(message);
297+
298+
_payloadService.Verify(p => p.CreateAsync(It.IsAny<WorkflowRequestEvent>()), Times.Never());
299+
}
300+
279301
private static MessageReceivedEventArgs CreateMessageReceivedEventArgs(string[] destinations)
280302
{
281303
var exportRequestMessage = new ExportRequestEvent

tests/UnitTests/WorkflowExecuter.Tests/Services/WorkflowExecuterServiceTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ public WorkflowExecuterServiceTests()
8787
Topics = new MessageBrokerConfigurationKeys { TaskDispatchRequest = "md.task.dispatch", ExportRequestPrefix = "md.export.request" },
8888
DicomAgents = new DicomAgentConfiguration { DicomWebAgentName = "monaidicomweb" }
8989
},
90-
MigExternalAppPlugins = new List<string> { { "examplePlugin" } }
91-
});
90+
MigExternalAppPlugins = new List<string> { { "examplePlugin" } }.ToArray()
91+
}) ;
9292

9393
_storageConfiguration = Options.Create(new StorageServiceConfiguration() { Settings = new Dictionary<string, string> { { "bucket", "testbucket" }, { "endpoint", "localhost" }, { "securedConnection", "False" } } });
9494

0 commit comments

Comments
 (0)