Skip to content

Commit 18a99ed

Browse files
authored
Merge pull request #943 from Project-MONAI/AI-376
Ai 376
2 parents acd4284 + f2b19c8 commit 18a99ed

File tree

24 files changed

+435
-10
lines changed

24 files changed

+435
-10
lines changed

src/Common/Configuration/WorkflowManagerOptions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ public class WorkflowManagerOptions : PagedOptions
7474
[ConfigurationKeyName("migExternalAppPlugins")]
7575
public string[] MigExternalAppPlugins { get; set; }
7676

77+
[ConfigurationKeyName("dataRetentionDays")]
78+
public int DataRetentionDays { get; set; }
79+
7780
public WorkflowManagerOptions()
7881
{
7982
Messaging = new MessageBrokerConfiguration();

src/WorkflowManager/Common/Interfaces/IPayloadService.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,13 @@ Task<IList<PayloadDto>> GetAllAsync(int? skip = null,
5454
/// <param name="payload"></param>
5555
/// <returns></returns>
5656
Task<bool> UpdateWorkflowInstanceIdsAsync(string payloadId, IEnumerable<string> workflowInstances);
57+
58+
/// <summary>
59+
/// Gets the expiry date for a payload.
60+
/// </summary>
61+
/// <param name="now"></param>
62+
/// <param name="workflowInstanceId"></param>
63+
/// <returns>date of expiry or null</returns>
64+
Task<DateTime?> GetExpiry(DateTime now, string? workflowInstanceId);
5765
}
5866
}

src/WorkflowManager/Common/Monai.Deploy.WorkflowManager.Common.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<AdditionalFiles Include="..\..\.sonarlint\project-monai_monai-deploy-workflow-manager\CSharp\SonarLint.xml" Link="SonarLint.xml" />
3232
</ItemGroup>
3333
<ItemGroup>
34+
<ProjectReference Include="..\..\Common\Configuration\Monai.Deploy.WorkflowManager.Common.Configuration.csproj" />
3435
<ProjectReference Include="..\Contracts\Monai.Deploy.WorkflowManager.Contracts.csproj" />
3536
<ProjectReference Include="..\Database\Monai.Deploy.WorkflowManager.Database.csproj" />
3637
<ProjectReference Include="..\Storage\Monai.Deploy.WorkflowManager.Storage.csproj" />

src/WorkflowManager/Common/Services/PayloadService.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
using Monai.Deploy.WorkflowManager.Common.Database.Interfaces;
2626
using Monai.Deploy.WorkflowManager.Common.Logging;
2727
using Monai.Deploy.WorkflowManager.Common.Storage.Services;
28+
using Microsoft.Extensions.Options;
29+
using Monai.Deploy.WorkflowManager.Common.Configuration;
2830

2931
namespace Monai.Deploy.WorkflowManager.Common.Miscellaneous.Services
3032
{
@@ -34,23 +36,31 @@ public class PayloadService : IPayloadService
3436

3537
private readonly IWorkflowInstanceRepository _workflowInstanceRepository;
3638

39+
private readonly IWorkflowRepository _workflowRepository;
40+
3741
private readonly IDicomService _dicomService;
3842

3943
private readonly IStorageService _storageService;
4044

45+
private readonly WorkflowManagerOptions _options;
46+
4147
private readonly ILogger<PayloadService> _logger;
4248

4349
public PayloadService(
4450
IPayloadRepository payloadRepository,
4551
IDicomService dicomService,
4652
IWorkflowInstanceRepository workflowInstanceRepository,
53+
IWorkflowRepository workflowRepository,
4754
IServiceScopeFactory serviceScopeFactory,
55+
IOptions<WorkflowManagerOptions> options,
4856
ILogger<PayloadService> logger)
4957
{
5058
_payloadRepository = payloadRepository ?? throw new ArgumentNullException(nameof(payloadRepository));
5159
_workflowInstanceRepository = workflowInstanceRepository ?? throw new ArgumentNullException(nameof(workflowInstanceRepository));
5260
_dicomService = dicomService ?? throw new ArgumentNullException(nameof(dicomService));
5361
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
62+
_workflowRepository = workflowRepository ?? throw new ArgumentNullException(nameof(workflowRepository));
63+
_options = options?.Value ?? throw new ArgumentNullException(nameof(options));
5464

5565
var scopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
5666
var scope = scopeFactory.CreateScope();
@@ -85,7 +95,8 @@ public PayloadService(
8595
DataTrigger = eventPayload.DataTrigger,
8696
Timestamp = eventPayload.Timestamp,
8797
PatientDetails = patientDetails,
88-
PayloadDeleted = PayloadDeleted.No
98+
PayloadDeleted = PayloadDeleted.No,
99+
Expires = await GetExpiry(DateTime.UtcNow, eventPayload.WorkflowInstanceId)
89100
};
90101

91102
if (await _payloadRepository.CreateAsync(payload))
@@ -106,6 +117,27 @@ public PayloadService(
106117
return null;
107118
}
108119

120+
public async Task<DateTime?> GetExpiry(DateTime now, string? workflowInstanceId)
121+
{
122+
var daysToKeep = await GetWorkflowDataExpiry(workflowInstanceId);
123+
daysToKeep ??= _options.DataRetentionDays;
124+
125+
if (daysToKeep == -1) { return null; }
126+
127+
return now.AddDays(daysToKeep.Value);
128+
}
129+
130+
private async Task<int?> GetWorkflowDataExpiry(string? workflowInstanceId)
131+
{
132+
if (string.IsNullOrWhiteSpace(workflowInstanceId)) { return null; }
133+
134+
var workflowInstance = await _workflowInstanceRepository.GetByWorkflowInstanceIdAsync(workflowInstanceId);
135+
136+
if (workflowInstance is null) { return null; }
137+
138+
return (await _workflowRepository.GetByWorkflowIdAsync(workflowInstance.WorkflowId))?.Workflow?.DataRetentionDays ?? null;
139+
}
140+
109141
public async Task<Payload> GetByIdAsync(string payloadId)
110142
{
111143
ArgumentNullException.ThrowIfNullOrWhiteSpace(payloadId, nameof(payloadId));
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// Copyright 2023 Guy’s and St Thomas’ NHS Foundation Trust
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
using Monai.Deploy.WorkflowManager.Common.Contracts.Models;
17+
using Mongo.Migration.Migrations.Document;
18+
using MongoDB.Bson;
19+
20+
namespace Monai.Deploy.WorkflowManager.Common.Contracts.Migrations
21+
{
22+
public class M004_Payload_Expires : DocumentMigration<Payload>
23+
{
24+
public M004_Payload_Expires() : base("1.0.4") { }
25+
26+
public override void Up(BsonDocument document)
27+
{
28+
document.Add("Expires", BsonNull.Create(null).ToJson(), true); //null = never expires
29+
}
30+
31+
public override void Down(BsonDocument document)
32+
{
33+
try
34+
{
35+
document.Remove("DataTrigger");
36+
}
37+
catch
38+
{ // can ignore we dont want failures stopping startup !
39+
}
40+
}
41+
}
42+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// Copyright 2023 Guy’s and St Thomas’ NHS Foundation Trust
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
using Monai.Deploy.WorkflowManager.Common.Contracts.Models;
17+
using Mongo.Migration.Migrations.Document;
18+
using MongoDB.Bson;
19+
20+
21+
namespace Monai.Deploy.WorkflowManager.Common.Contracts.Migrations
22+
{
23+
public class M004_WorkflowRevision_AddDataRetension : DocumentMigration<WorkflowRevision>
24+
{
25+
public M004_WorkflowRevision_AddDataRetension() : base("1.0.1") { }
26+
27+
public override void Up(BsonDocument document)
28+
{
29+
// document.Add("Workflow.DataRetentionDays", BsonNull.Create(null).ToJson(), true);
30+
var workflow = document["Workflow"].AsBsonDocument;
31+
workflow.Add("DataRetentionDays", BsonNull.Create(null).ToJson(), true);
32+
}
33+
34+
public override void Down(BsonDocument document)
35+
{
36+
try
37+
{
38+
var workflow = document["Workflow"].AsBsonDocument;
39+
workflow.Remove("DataRetentionDays");
40+
}
41+
catch
42+
{ // can ignore we dont want failures stopping startup !
43+
}
44+
}
45+
}
46+
}

src/WorkflowManager/Contracts/Models/Payload.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727

2828
namespace Monai.Deploy.WorkflowManager.Common.Contracts.Models
2929
{
30-
[CollectionLocation("Payloads"), RuntimeVersion("1.0.3")]
30+
[CollectionLocation("Payloads"), RuntimeVersion("1.0.4")]
3131
public class Payload : IDocument
3232
{
3333
[JsonConverter(typeof(DocumentVersionConvert)), BsonSerializer(typeof(DocumentVersionConverBson))]
34-
public DocumentVersion Version { get; set; } = new DocumentVersion(1, 0, 3);
34+
public DocumentVersion Version { get; set; } = new DocumentVersion(1, 0, 4);
3535

3636
[JsonProperty(PropertyName = "id")]
3737
public string Id { get; set; } = string.Empty;
@@ -67,6 +67,10 @@ public class Payload : IDocument
6767
public PatientDetails PatientDetails { get; set; } = new PatientDetails();
6868

6969
public DataOrigin DataTrigger { get; set; } = new DataOrigin { DataService = DataService.DIMSE };
70+
71+
[JsonProperty(PropertyName = "expires")]
72+
public DateTime? Expires { get; set; }
73+
7074
}
7175

7276
public enum PayloadDeleted

src/WorkflowManager/Contracts/Models/Workflow.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,8 @@ public class Workflow
3636
[JsonProperty(PropertyName = "tasks")]
3737
public TaskObject[] Tasks { get; set; } = System.Array.Empty<TaskObject>();
3838

39+
[JsonProperty(PropertyName = "dataRetentionDays")]
40+
public int? DataRetentionDays { get; set; } = 3;// note. -1 = never delete
41+
3942
}
4043
}

src/WorkflowManager/Contracts/Models/WorkflowRevision.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@
2323

2424
namespace Monai.Deploy.WorkflowManager.Common.Contracts.Models
2525
{
26-
[CollectionLocation("Workflows"), RuntimeVersion("1.0.0")]
26+
[CollectionLocation("Workflows"), RuntimeVersion("1.0.1")]
2727
public class WorkflowRevision : ISoftDeleteable, IDocument
2828
{
2929
[BsonId]
3030
[JsonProperty(PropertyName = "id")]
3131
public string? Id { get; set; }
3232

3333
[JsonConverter(typeof(DocumentVersionConvert)), BsonSerializer(typeof(DocumentVersionConverBson))]
34-
public DocumentVersion Version { get; set; } = new DocumentVersion(1, 0, 0);
34+
public DocumentVersion Version { get; set; } = new DocumentVersion(1, 0, 1);
3535

3636
[JsonProperty(PropertyName = "workflow_id")]
3737
public string WorkflowId { get; set; } = string.Empty;

src/WorkflowManager/Database/Interfaces/IPayloadRepository.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
using System;
1718
using System.Collections.Generic;
1819
using System.Threading.Tasks;
1920
using Monai.Deploy.WorkflowManager.Common.Contracts.Models;
@@ -52,11 +53,27 @@ public interface IPayloadRepository
5253
/// <returns>The updated payload.</returns>
5354
Task<bool> UpdateAsync(Payload payload);
5455

56+
/// <summary>
5557
/// Updates a payload in the database.
5658
/// </summary>
5759
/// <param name="payloadId"></param>
5860
/// <param name="workflowInstances"></param>
5961
/// <returns></returns>
6062
Task<bool> UpdateAssociatedWorkflowInstancesAsync(string payloadId, IEnumerable<string> workflowInstances);
63+
64+
/// <summary>
65+
/// Gets all the payloads that might need deleted
66+
/// </summary>
67+
/// <param name="now">the current datetime</param>
68+
/// <returns></returns>
69+
Task<IList<Payload>> GetPayloadsToDelete(DateTime now);
70+
71+
/// <summary>
72+
/// Marks a bunch of payloads as a new deleted state
73+
/// </summary>
74+
/// <param name="Ids">a list of payloadIds to mark in new status</param>
75+
/// <param name="status">the status to mark as</param>
76+
/// <returns></returns>
77+
Task MarkDeletedState(IList<string> Ids, PayloadDeleted status);
6178
}
6279
}

0 commit comments

Comments
 (0)