Skip to content

Commit 63714dd

Browse files
authored
Merge pull request #792 from Project-MONAI/release/0.1.14
Release/0.1.14
2 parents 58b2cde + 370bc14 commit 63714dd

File tree

17 files changed

+329
-70
lines changed

17 files changed

+329
-70
lines changed

src/Shared/Shared/ValidationConstants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static class ValidationConstants
6161
/// <summary>
6262
/// Key for the memory.
6363
/// </summary>
64-
public static readonly string Memory = "memory_gb";
64+
public static readonly string Memory = "memory";
6565

6666
/// <summary>
6767
/// Key for the GPU.

src/TaskManager/Plug-ins/Argo/StaticValues/Keys.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,6 @@ internal static class Keys
8888
/// </summary>
8989
public static readonly string TaskPriorityClassName = "priority";
9090

91-
/// <summary>
92-
/// Key for CPU
93-
/// </summary>
94-
public static readonly string Cpu = "cpu";
95-
96-
/// <summary>
97-
/// Key for memory allocation
98-
/// </summary>
99-
public static readonly string Memory = "memory_gb";
100-
101-
/// <summary>
102-
/// Key for GPU
103-
/// </summary>
104-
public static readonly string Gpu = "number_gpu";
105-
10691
/// <summary>
10792
/// Required arguments to run the Argo workflow.
10893
/// </summary>

src/TaskManager/Plug-ins/Argo/StaticValues/ResourcesKeys.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414
* limitations under the License.
1515
*/
1616

17+
using static Monai.Deploy.WorkflowManager.Shared.ValidationConstants;
18+
1719
namespace Monai.Deploy.WorkflowManager.TaskManager.Argo.StaticValues
1820
{
1921
public static class ResourcesKeys
2022
{
21-
public static readonly ResourcesKey GpuLimit = new() { TaskKey = "gpu_required", ArgoKey = "nvidia.com/gpu" };
23+
public static readonly ResourcesKey GpuLimit = new() { TaskKey = GpuRequired, ArgoKey = "nvidia.com/gpu" };
2224

23-
public static readonly ResourcesKey MemoryLimit = new() { TaskKey = "memory_gb", ArgoKey = "memory" };
25+
public static readonly ResourcesKey MemoryLimit = new() { TaskKey = Memory, ArgoKey = "memory" };
2426

25-
public static readonly ResourcesKey CpuLimit = new() { TaskKey = "cpu", ArgoKey = "cpu" };
27+
public static readonly ResourcesKey CpuLimit = new() { TaskKey = Cpu, ArgoKey = "cpu" };
2628
}
2729
}

src/WorkflowManager/Common/Services/PayloadService.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public PayloadService(
8686
CallingAeTitle = eventPayload.CallingAeTitle,
8787
Timestamp = eventPayload.Timestamp,
8888
PatientDetails = patientDetails,
89-
PayloadDeleted = PayloadDeleted.No,
89+
PayloadDeleted = PayloadDeleted.No
9090
};
9191

9292
if (await _payloadRepository.CreateAsync(payload))
@@ -173,12 +173,12 @@ public async Task<bool> DeletePayloadFromStorageAsync(string payloadId)
173173
throw new MonaiNotFoundException($"Payload with ID: {payloadId} not found");
174174
}
175175

176-
if (payload.PayloadDeleted == PayloadDeleted.InProgress)
176+
if (payload.PayloadDeleted == PayloadDeleted.InProgress || payload.PayloadDeleted == PayloadDeleted.Yes)
177177
{
178-
throw new MonaiBadRequestException($"Deletion of files for payload ID: {payloadId} already in progress");
178+
throw new MonaiBadRequestException($"Deletion of files for payload ID: {payloadId} already in progress or already deleted");
179179
}
180180

181-
// update the payload to in progress before we request deletion form MinIO
181+
// update the payload to in progress before we request deletion from storage
182182
payload.PayloadDeleted = PayloadDeleted.InProgress;
183183
await _payloadRepository.UpdateAsync(payload);
184184

@@ -188,12 +188,19 @@ public async Task<bool> DeletePayloadFromStorageAsync(string payloadId)
188188
{
189189
try
190190
{
191-
await _storageService.RemoveObjectsAsync(payload.Bucket, payload.Files.Select(f => f.Path));
191+
// get all objects for the payload in storage to be deleted
192+
var allPayloadObjects = await _storageService.ListObjectsAsync(payload.Bucket, payloadId, true);
193+
194+
if (allPayloadObjects.Any())
195+
{
196+
await _storageService.RemoveObjectsAsync(payload.Bucket, allPayloadObjects.Select(o => o.FilePath));
197+
}
198+
192199
payload.PayloadDeleted = PayloadDeleted.Yes;
193200
}
194-
catch
201+
catch (Exception ex)
195202
{
196-
_logger.PayloadUpdateFailed(payloadId);
203+
_logger.PayloadDeleteFailed(payloadId, ex);
197204
payload.PayloadDeleted = PayloadDeleted.Failed;
198205
}
199206
finally

src/WorkflowManager/Database/Interfaces/IWorkflowRepository.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using System;
1818
using System.Collections.Generic;
1919
using System.Threading.Tasks;
20+
using Monai.Deploy.Messaging.Events;
2021
using Monai.Deploy.WorkflowManager.Contracts.Models;
2122

2223
namespace Monai.Deploy.WorkflowManager.Database.Interfaces
@@ -67,6 +68,23 @@ public interface IWorkflowRepository
6768
/// <param name="aeTitle">An aeTitle to retrieve workflows for.</param>
6869
Task<IList<WorkflowRevision>> GetWorkflowsByAeTitleAsync(List<string> aeTitles);
6970

71+
/// <summary>
72+
/// Retrieves a list of workflows based..<br/>
73+
/// if clinical workflow has AET no data origin. => WorkflowRequestEvents received with CalledAET with that AET this workflow (regardless of what the CallingAET is)<br/>
74+
/// if clinical workflow has AET and data_orgins => only WorkflowRequestEvents with CalledAET with that AET and CallingAET trigger this workflow.<br/>
75+
/// </summary>
76+
/// <example>
77+
/// If clinical workflow (workflow revision) exists with AET “MONAI” but no data_origins set
78+
/// Any inbound WorkflowRequestEvents with CalledAET = “MONAI” trigger this workflow (regardless of what the CallingAET is)
79+
///
80+
/// If clinical workflow (workflow revision) exists with AET “MONAI” and data_origins set as “PACS”
81+
/// Only inbound WorkflowRequestEvents with CalledAET = “MONAI” and CallingAET = “PACS” trigger this workflow
82+
/// </example>
83+
/// <param name="calledAeTitle"></param>
84+
/// <param name="sallingAeTitle"></param>
85+
/// <returns></returns>
86+
Task<IList<WorkflowRevision>> GetWorkflowsForWorkflowRequestAsync(string calledAeTitle, string callingAeTitle);
87+
7088
/// <summary>
7189
/// Creates a workflow object.
7290
/// </summary>

src/WorkflowManager/Database/Repositories/WorkflowRepository.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,29 @@ public async Task<IList<WorkflowRevision>> GetWorkflowsByAeTitleAsync(List<strin
199199
return workflows;
200200
}
201201

202+
public async Task<IList<WorkflowRevision>> GetWorkflowsForWorkflowRequestAsync(string calledAeTitle, string callingAeTitle)
203+
{
204+
Guard.Against.NullOrEmpty(calledAeTitle);
205+
Guard.Against.NullOrEmpty(callingAeTitle);
206+
207+
var wfs = await _workflowCollection
208+
.Find(x =>
209+
x.Workflow != null &&
210+
x.Workflow.InformaticsGateway != null &&
211+
((x.Workflow.InformaticsGateway.AeTitle == calledAeTitle &&
212+
(x.Workflow.InformaticsGateway.DataOrigins == null ||
213+
x.Workflow.InformaticsGateway.DataOrigins.Length == 0)) ||
214+
x.Workflow.InformaticsGateway.AeTitle == calledAeTitle &&
215+
x.Workflow.InformaticsGateway.DataOrigins != null &&
216+
x.Workflow.InformaticsGateway.DataOrigins.Any(d => d == callingAeTitle)) &&
217+
x.Deleted == null)
218+
.ToListAsync();
219+
return wfs;
220+
}
221+
202222
public async Task<string> CreateAsync(Workflow workflow)
203223
{
204-
Guard.Against.Null(workflow, nameof(workflow));
224+
Guard.Against.Null(workflow);
205225

206226
var workflowRevision = new WorkflowRevision
207227
{

src/WorkflowManager/Logging/Log.300000.Payload.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,8 @@ public static partial class Log
3737

3838
[LoggerMessage(EventId = 300005, Level = LogLevel.Error, Message = "Failed to update payload {payloadId} due to database error.")]
3939
public static partial void PayloadUpdateFailed(this ILogger logger, string payloadId);
40+
41+
[LoggerMessage(EventId = 300006, Level = LogLevel.Error, Message = "Failed to delete payload {payloadId} from storage.")]
42+
public static partial void PayloadDeleteFailed(this ILogger logger, string payloadId, Exception ex);
4043
}
4144
}

src/WorkflowManager/WorkflowExecuter/Services/WorkflowExecuterService.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,8 @@ public async Task<bool> ProcessPayload(WorkflowRequestEvent message, Payload pay
117117
}
118118
else
119119
{
120-
var aeTitles = new List<string>
121-
{
122-
message.CalledAeTitle,
123-
message.CallingAeTitle
124-
};
125-
126-
workflows = await _workflowRepository.GetWorkflowsByAeTitleAsync(aeTitles) as List<WorkflowRevision>;
120+
var result = await _workflowRepository.GetWorkflowsForWorkflowRequestAsync(message.CalledAeTitle, message.CallingAeTitle);
121+
workflows = new List<WorkflowRevision>(result);
127122
}
128123

129124
if (workflows is null || workflows.Any() is false)

src/WorkflowManager/WorkflowManager/Validators/WorkflowValidator.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -375,16 +375,13 @@ private void ValidateArgoTask(TaskObject currentTask)
375375
}
376376
}
377377

378-
new List<string> { Cpu, Memory }.ForEach(key =>
378+
if (
379+
currentTask.Args.TryGetValue(Cpu, out var val) &&
380+
(string.IsNullOrEmpty(val) ||
381+
(double.TryParse(val, out double parsedVal) && (parsedVal < 1 || Math.Truncate(parsedVal) != parsedVal))))
379382
{
380-
if (
381-
currentTask.Args.TryGetValue(key, out var val) &&
382-
(string.IsNullOrEmpty(val) ||
383-
(double.TryParse(val, out double parsedVal) && (parsedVal < 1 || Math.Truncate(parsedVal) != parsedVal))))
384-
{
385-
Errors.Add($"Task: '{currentTask.Id}' value '{val}' provided for argument '{key}' is not valid. The value needs to be a whole number greater than 0.");
386-
}
387-
});
383+
Errors.Add($"Task: '{currentTask.Id}' value '{val}' provided for argument '{Cpu}' is not valid. The value needs to be a whole number greater than 0.");
384+
}
388385

389386
if (
390387
currentTask.Args.TryGetValue(GpuRequired, out var gpuRequired) &&

tests/IntegrationTests/WorkflowExecutor.IntegrationTests/Features/PayloadApi.feature

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,32 @@ Scenario Outline: Get payload by Id returns 400
124124
When I send a GET request
125125
Then I will get a 400 response
126126
And I will receive the error message Failed to validate id, not a valid guid
127+
128+
@DeletePayloadById
129+
Scenario Outline: Delete payload by Id returns 400 with invalid payload ID
130+
Given I have an endpoint /payload/invalid-payload-id
131+
When I send a DELETE request
132+
Then I will get a 400 response
133+
And I will receive the error message Failed to validate id, not a valid guid
134+
135+
@DeletePayloadById
136+
Scenario Outline: Delete payload by ID returns 404 when no payload exists
137+
Given I have an endpoint /payload/c5c3635b-81dd-44a9-8c3b-71adec7d47c6
138+
When I send a DELETE request
139+
Then I will get a 404 response
140+
And I will receive the error message Payload with ID: c5c3635b-81dd-44a9-8c3b-71adec7d47c6 not found
141+
142+
@DeletePayloadById
143+
Scenario Outline: Delete payload by ID returns 400 when PayloadDeleted is already InProgress
144+
Given I have an endpoint /payload/c5c3635b-81dd-44a9-8c3b-71adec7d47c6
145+
And I have a payload saved in mongo Payload_PayloadDeleted_InProgress
146+
When I send a DELETE request
147+
Then I will get a 400 response
148+
And I will receive the error message Deletion of files for payload ID: c5c3635b-81dd-44a9-8c3b-71adec7d47c6 already in progress or already deleted
149+
150+
@DeletePayloadById
151+
Scenario Outline: Delete payload by ID returns 202
152+
Given I have an endpoint /payload/d5c3633b-41de-44a9-8c3a-71adec3d47c1
153+
And I have a payload saved in mongo Payload_PayloadDeleted_No
154+
When I send a DELETE request
155+
Then I will get a 202 response

0 commit comments

Comments
 (0)