@@ -54,8 +54,9 @@ public abstract class ExportServiceBase : IHostedService, IMonaiService
54
54
{
55
55
private static readonly object SyncRoot = new ( ) ;
56
56
57
- internal event EventHandler ReportActionStarted ;
57
+ internal event EventHandler ReportActionCompleted ;
58
58
59
+ private readonly CancellationTokenSource _cancellationTokenSource ;
59
60
private readonly ILogger _logger ;
60
61
private readonly IServiceScopeFactory _serviceScopeFactory ;
61
62
private readonly IStorageInfoProvider _storageInfoProvider ;
@@ -64,8 +65,6 @@ public abstract class ExportServiceBase : IHostedService, IMonaiService
64
65
private readonly IMessageBrokerPublisherService _messagePublisher ;
65
66
private readonly IServiceScope _scope ;
66
67
private readonly Dictionary < string , ExportRequestMessage > _exportRequests ;
67
- private readonly string _exportQueueName ;
68
- private TransformManyBlock < ExportRequestMessage , ExportRequestDataMessage > _exportFlow ;
69
68
70
69
public abstract string RoutingKey { get ; }
71
70
protected abstract int Concurrency { get ; }
@@ -87,6 +86,7 @@ public ExportServiceBase(
87
86
IServiceScopeFactory serviceScopeFactory ,
88
87
IStorageInfoProvider storageInfoProvider )
89
88
{
89
+ _cancellationTokenSource = new CancellationTokenSource ( ) ;
90
90
_logger = logger ?? throw new ArgumentNullException ( nameof ( logger ) ) ;
91
91
_serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException ( nameof ( serviceScopeFactory ) ) ;
92
92
_scope = _serviceScopeFactory . CreateScope ( ) ;
@@ -103,12 +103,10 @@ public ExportServiceBase(
103
103
_messagePublisher = _scope . ServiceProvider . GetRequiredService < IMessageBrokerPublisherService > ( ) ;
104
104
105
105
_exportRequests = new Dictionary < string , ExportRequestMessage > ( ) ;
106
- _exportQueueName = _configuration . Messaging . Topics . ExportRequestQueue ;
107
106
}
108
107
109
108
public Task StartAsync ( CancellationToken cancellationToken )
110
109
{
111
- SetupExportFlow ( cancellationToken ) ;
112
110
SetupPolling ( ) ;
113
111
114
112
Status = ServiceStatus . Running ;
@@ -118,44 +116,73 @@ public Task StartAsync(CancellationToken cancellationToken)
118
116
119
117
public Task StopAsync ( CancellationToken cancellationToken )
120
118
{
119
+ _cancellationTokenSource . Cancel ( ) ;
121
120
_logger . LogInformation ( $ "{ ServiceName } is stopping.") ;
122
- _exportFlow . Complete ( ) ;
123
- _exportFlow . Completion . Wait ( cancellationToken ) ;
124
121
Status = ServiceStatus . Stopped ;
125
122
return Task . CompletedTask ;
126
123
}
127
124
128
- private void SetupExportFlow ( CancellationToken cancellationToken )
125
+ private void SetupPolling ( )
129
126
{
127
+ _messageSubscriber . Subscribe ( RoutingKey , String . Empty , OnMessageReceivedCallback ) ;
128
+ _logger . Log ( LogLevel . Information , $ "{ ServiceName } subscribed to { RoutingKey } messages.") ;
129
+ }
130
+
131
+ private void OnMessageReceivedCallback ( MessageReceivedEventArgs eventArgs )
132
+ {
133
+ if ( ! _storageInfoProvider . HasSpaceAvailableForExport )
134
+ {
135
+ _logger . Log ( LogLevel . Warning , $ "Export service paused due to insufficient storage space. Available storage space: { _storageInfoProvider . AvailableFreeSpace : D} .") ;
136
+ _messageSubscriber . Reject ( eventArgs . Message ) ;
137
+ return ;
138
+ }
139
+
130
140
try
131
141
{
132
142
var executionOptions = new ExecutionDataflowBlockOptions
133
143
{
134
144
MaxDegreeOfParallelism = Concurrency ,
135
145
MaxMessagesPerTask = 1 ,
136
- CancellationToken = cancellationToken
146
+ CancellationToken = _cancellationTokenSource . Token
137
147
} ;
138
148
139
- _exportFlow = new TransformManyBlock < ExportRequestMessage , ExportRequestDataMessage > (
140
- ( exportRequest ) => DownloadPayloadActionCallback ( exportRequest , cancellationToken ) ,
149
+ var exportFlow = new TransformManyBlock < ExportRequestMessage , ExportRequestDataMessage > (
150
+ ( exportRequest ) => DownloadPayloadActionCallback ( exportRequest , _cancellationTokenSource . Token ) ,
141
151
executionOptions ) ;
142
152
143
153
var exportActionBlock = new TransformBlock < ExportRequestDataMessage , ExportRequestDataMessage > (
144
154
async ( exportDataRequest ) =>
145
155
{
146
156
if ( exportDataRequest . IsFailed ) return exportDataRequest ;
147
- return await ExportDataBlockCallback ( exportDataRequest , cancellationToken ) ;
157
+ return await ExportDataBlockCallback ( exportDataRequest , _cancellationTokenSource . Token ) ;
148
158
} ,
149
159
executionOptions ) ;
150
160
151
161
var reportingActionBlock = new ActionBlock < ExportRequestDataMessage > ( ReportingActionBlock , executionOptions ) ;
152
162
153
163
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true } ;
154
164
155
- _exportFlow . LinkTo ( exportActionBlock , linkOptions ) ;
165
+ exportFlow . LinkTo ( exportActionBlock , linkOptions ) ;
156
166
exportActionBlock . LinkTo ( reportingActionBlock , linkOptions ) ;
157
167
158
- _logger . Log ( LogLevel . Information , $ "{ ServiceName } completed workflow setup.") ;
168
+ lock ( SyncRoot )
169
+ {
170
+ var exportRequest = eventArgs . Message . ConvertTo < ExportRequestMessage > ( ) ;
171
+ if ( _exportRequests . ContainsKey ( exportRequest . ExportTaskId ) )
172
+ {
173
+ _logger . Log ( LogLevel . Warning , $ "The export request { exportRequest . ExportTaskId } is already queued for export.") ;
174
+ return ;
175
+ }
176
+
177
+ exportRequest . MessageId = eventArgs . Message . MessageId ;
178
+ exportRequest . DeliveryTag = eventArgs . Message . DeliveryTag ;
179
+
180
+ _exportRequests . Add ( exportRequest . ExportTaskId , exportRequest ) ;
181
+ exportFlow . Post ( exportRequest ) ;
182
+ }
183
+
184
+ exportFlow . Complete ( ) ;
185
+ reportingActionBlock . Completion . Wait ( _cancellationTokenSource . Token ) ;
159
186
}
160
187
catch ( AggregateException ex )
161
188
{
@@ -170,38 +197,6 @@ private void SetupExportFlow(CancellationToken cancellationToken)
170
197
}
171
198
}
172
199
173
- private void SetupPolling ( )
174
- {
175
- _messageSubscriber . Subscribe ( RoutingKey , _exportQueueName , OnMessageReceivedCallback ) ;
176
- _logger . Log ( LogLevel . Information , $ "{ ServiceName } subscribed to { RoutingKey } messages.") ;
177
- }
178
-
179
- private void OnMessageReceivedCallback ( MessageReceivedEventArgs eventArgs )
180
- {
181
- if ( ! _storageInfoProvider . HasSpaceAvailableForExport )
182
- {
183
- _logger . Log ( LogLevel . Warning , $ "Export service paused due to insufficient storage space. Available storage space: { _storageInfoProvider . AvailableFreeSpace : D} .") ;
184
- _messageSubscriber . Reject ( eventArgs . Message ) ;
185
- return ;
186
- }
187
-
188
- lock ( SyncRoot )
189
- {
190
- var exportRequest = eventArgs . Message . ConvertTo < ExportRequestMessage > ( ) ;
191
- if ( _exportRequests . ContainsKey ( exportRequest . ExportTaskId ) )
192
- {
193
- _logger . Log ( LogLevel . Warning , $ "The export request { exportRequest . ExportTaskId } is already queued for export.") ;
194
- return ;
195
- }
196
-
197
- exportRequest . MessageId = eventArgs . Message . MessageId ;
198
- exportRequest . DeliveryTag = eventArgs . Message . DeliveryTag ;
199
-
200
- _exportRequests . Add ( exportRequest . ExportTaskId , exportRequest ) ;
201
- _exportFlow . Post ( exportRequest ) ;
202
- }
203
- }
204
-
205
200
private IEnumerable < ExportRequestDataMessage > DownloadPayloadActionCallback ( ExportRequestMessage exportRequest , CancellationToken cancellationToken )
206
201
{
207
202
Guard . Against . Null ( exportRequest , nameof ( exportRequest ) ) ;
@@ -277,12 +272,6 @@ private void ReportingActionBlock(ExportRequestDataMessage exportRequestData)
277
272
278
273
_logger . Log ( LogLevel . Information , $ "Export task completed with { exportRequest . FailedFiles } failures out of { exportRequest . Files . Count ( ) } ") ;
279
274
280
- if ( ReportActionStarted != null )
281
- {
282
- _logger . Log ( LogLevel . Debug , $ "Calling ReportActionStarted callback.") ;
283
- ReportActionStarted ( this , null ) ;
284
- }
285
-
286
275
var exportCompleteMessage = new ExportCompleteMessage ( exportRequest ) ;
287
276
var jsonMessage = new JsonMessage < ExportCompleteMessage > ( exportCompleteMessage , exportRequest . CorrelationId , exportRequest . DeliveryTag ) ;
288
277
@@ -318,6 +307,12 @@ private void ReportingActionBlock(ExportRequestDataMessage exportRequestData)
318
307
{
319
308
_exportRequests . Remove ( exportRequestData . ExportTaskId ) ;
320
309
}
310
+
311
+ if ( ReportActionCompleted != null )
312
+ {
313
+ _logger . Log ( LogLevel . Debug , $ "Calling ReportActionCompleted callback.") ;
314
+ ReportActionCompleted ( this , null ) ;
315
+ }
321
316
}
322
317
}
323
318
}
0 commit comments