Skip to content

Commit a83ef62

Browse files
authored
Resets ActionBlock if faulted or cancelled. (#385)
* Resets ActionBlock if faulted or cancelled. * Log number of uploaded files. Signed-off-by: Victor Chang <[email protected]>
1 parent 1e63847 commit a83ef62

18 files changed

+328
-140
lines changed

src/Api/Storage/Payload.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public TimeSpan Elapsed
7676
public string? CalledAeTitle { get => Files.OfType<DicomFileStorageMetadata>().Select(p => p.CalledAeTitle).FirstOrDefault(); }
7777

7878
public int FilesUploaded { get => Files.Count(p => p.IsUploaded); }
79+
7980
public int FilesFailedToUpload { get => Files.Count(p => p.IsUploadFailed); }
8081

8182
public Payload(string key, string correlationId, uint timeout)

src/Common/ExtensionMethods.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,15 @@ public static async Task<bool> Post<TInput>(this ActionBlock<TInput> actionBlock
7676
await Task.Delay(delay).ConfigureAwait(false);
7777
return actionBlock.Post(input);
7878
}
79+
80+
/// <summary>
81+
/// Checks if a given task is faulted or cancelled.
82+
/// </summary>
83+
/// <param name="task">The task object</param>
84+
/// <returns>True if canceled or faulted. False otherwise.</returns>
85+
public static bool IsCanceledOrFaulted(this Task task)
86+
{
87+
return task.IsCanceled || task.IsFaulted;
88+
}
7989
}
8090
}

src/Configuration/DicomWebConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class DicomWebConfiguration
3939
/// Gets or sets the maximum number of simultaneous DICOMweb connections.
4040
/// </summary>
4141
[ConfigurationKeyName("maximumNumberOfConnections")]
42-
public int MaximumNumberOfConnection { get; set; } = 2;
42+
public ushort MaximumNumberOfConnection { get; set; } = 2;
4343

4444
/// <summary>
4545
/// Gets or set the maximum allowed file size in bytes with default to 2GiB.

src/Configuration/ScuConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class ScuConfiguration
5454
/// Gets or sets the maximum number of simultaneous DICOM associations for the SCU service.
5555
/// </summary>
5656
[ConfigurationKeyName("maximumNumberOfAssociations")]
57-
public int MaximumNumberOfAssociations { get; set; } = 8;
57+
public ushort MaximumNumberOfAssociations { get; set; } = 8;
5858

5959
public ScuConfiguration()
6060
{
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2023 MONAI Consortium
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+
17+
using System;
18+
using System.Runtime.Serialization;
19+
using Monai.Deploy.InformaticsGateway.Api.Storage;
20+
21+
namespace Monai.Deploy.InformaticsGateway.Common
22+
{
23+
internal class PostPayloadException : Exception
24+
{
25+
public Payload.PayloadState TargetQueue { get; }
26+
public Payload Payload { get; }
27+
28+
public PostPayloadException()
29+
{
30+
}
31+
32+
public PostPayloadException(Api.Storage.Payload.PayloadState targetState, Payload payload)
33+
{
34+
TargetQueue = targetState;
35+
Payload = payload;
36+
}
37+
38+
public PostPayloadException(string message) : base(message)
39+
{
40+
}
41+
42+
public PostPayloadException(string message, Exception innerException) : base(message, innerException)
43+
{
44+
}
45+
46+
protected PostPayloadException(SerializationInfo info, StreamingContext context) : base(info, context)
47+
{
48+
}
49+
}
50+
}

src/InformaticsGateway/Logging/Log.3000.PayloadAssembler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 MONAI Consortium
2+
* Copyright 2022-2023 MONAI Consortium
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,8 +33,8 @@ public static partial class Log
3333
[LoggerMessage(EventId = 3004, Level = LogLevel.Trace, Message = "Number of incomplete payloads waiting for processing: {count}.")]
3434
public static partial void BucketsActive(this ILogger logger, int count);
3535

36-
[LoggerMessage(EventId = 3005, Level = LogLevel.Trace, Message = "Checking elapsed time for bucket: {key} with timeout set to {timeout}s. Elapsed {elapsed}s with {failedFiles} failures out of {totalNumberOfFiles}.")]
37-
public static partial void BucketElapsedTime(this ILogger logger, string key, uint timeout, double elapsed, int totalNumberOfFiles, int failedFiles);
36+
[LoggerMessage(EventId = 3005, Level = LogLevel.Trace, Message = "Checking elapsed time for bucket: {key} with timeout set to {timeout}s. Elapsed {elapsed}s with {succeededFiles} uplaoded and {failedFiles} failures out of {totalNumberOfFiles}.")]
37+
public static partial void BucketElapsedTime(this ILogger logger, string key, uint timeout, double elapsed, int totalNumberOfFiles, int succeededFiles, int failedFiles);
3838

3939
[LoggerMessage(EventId = 3007, Level = LogLevel.Information, Message = "Bucket {key} sent to processing queue with {count} files.")]
4040
public static partial void BucketReady(this ILogger logger, string key, int count);

src/InformaticsGateway/Logging/Log.500.ExportService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,11 @@ public static partial class Log
123123

124124
[LoggerMessage(EventId = 533, Level = LogLevel.Error, Message = "Recovering messaging service connection due to {reason}.")]
125125
public static partial void MessagingServiceErrorRecover(this ILogger logger, string reason);
126+
127+
[LoggerMessage(EventId = 534, Level = LogLevel.Error, Message = "Error posting export job for processing correlation ID {correlationId}, export task ID {exportTaskId}.")]
128+
public static partial void ErrorPostingExportJobToQueue(this ILogger logger, string correlationId, string exportTaskId);
129+
130+
[LoggerMessage(EventId = 535, Level = LogLevel.Warning, Message = "Exceeded maximum number of worker in {serviceName}: {count}.")]
131+
public static partial void ExceededMaxmimumNumberOfWorkers(this ILogger logger, string serviceName, ulong count);
126132
}
127133
}

src/InformaticsGateway/Logging/Log.700.PayloadService.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,17 @@ public static partial class Log
136136

137137
[LoggerMessage(EventId = 743, Level = LogLevel.Error, Message = "Exception moving payload.")]
138138
public static partial void PayloadMoveException(this ILogger logger, Exception ex);
139+
140+
[LoggerMessage(EventId = 744, Level = LogLevel.Warning, Message = "PayloadNotification move payload queue: faulted: {isFauled}, cancelled: {isCancelled}.")]
141+
public static partial void MoveQueueFaulted(this ILogger logger, bool isFauled, bool isCancelled);
142+
143+
[LoggerMessage(EventId = 745, Level = LogLevel.Warning, Message = "PayloadNotification publishing payload queue: faulted: {isFauled}, cancelled: {isCancelled}.")]
144+
public static partial void PublishQueueFaulted(this ILogger logger, bool isFauled, bool isCancelled);
145+
146+
[LoggerMessage(EventId = 746, Level = LogLevel.Error, Message = "Error posting payload to move queue.")]
147+
public static partial void ErrorPostingJobToMovePayloadsQueue(this ILogger logger);
148+
149+
[LoggerMessage(EventId = 747, Level = LogLevel.Error, Message = "Error posting payload to publish queue.")]
150+
public static partial void ErrorPostingJobToPublishPayloadsQueue(this ILogger logger);
139151
}
140152
}

src/InformaticsGateway/Services/Connectors/PayloadAssembler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ private async void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
135135
var payload = await _payloads[key].Task.ConfigureAwait(false);
136136
using var loggerScope = _logger.BeginScope(new LoggingDataDictionary<string, object> { { "CorrelationId", payload.CorrelationId } });
137137

138-
_logger.BucketElapsedTime(key, payload.Timeout, payload.ElapsedTime().TotalSeconds, payload.Files.Count, payload.FilesFailedToUpload);
138+
_logger.BucketElapsedTime(key, payload.Timeout, payload.ElapsedTime().TotalSeconds, payload.Files.Count, payload.FilesUploaded, payload.FilesFailedToUpload);
139139
// Wait for timer window closes before sending payload for processing
140140
if (payload.HasTimedOut)
141141
{

src/InformaticsGateway/Services/Connectors/PayloadMoveActionHandler.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ public async Task MoveFilesAsync(Payload payload, ActionBlock<Payload> moveQueue
8686
var action = await UpdatePayloadState(payload, ex, cancellationToken).ConfigureAwait(false);
8787
if (action == PayloadAction.Updated)
8888
{
89-
await moveQueue.Post(payload, _options.Value.Storage.Retries.RetryDelays.ElementAt(payload.RetryCount - 1)).ConfigureAwait(false);
89+
if (!await moveQueue.Post(payload, _options.Value.Storage.Retries.RetryDelays.ElementAt(payload.RetryCount - 1)).ConfigureAwait(false))
90+
{
91+
throw new PostPayloadException(Payload.PayloadState.Move, payload);
92+
}
9093
}
9194
}
9295
finally
@@ -111,7 +114,11 @@ private async Task NotifyIfCompleted(Payload payload, ActionBlock<Payload> notif
111114
await repository.UpdateAsync(payload, cancellationToken).ConfigureAwait(false);
112115
_logger.PayloadSaved(payload.PayloadId);
113116

114-
notificationQueue.Post(payload);
117+
if (!notificationQueue.Post(payload))
118+
{
119+
throw new PostPayloadException(Payload.PayloadState.Notify, payload);
120+
}
121+
115122
_logger.PayloadReadyToBePublished(payload.PayloadId);
116123
}
117124
else // we should never hit this else block.

0 commit comments

Comments
 (0)