@@ -88,16 +88,38 @@ public PayloadNotificationService(IServiceScopeFactory serviceScopeFactory,
88
88
_cancellationTokenSource = new CancellationTokenSource ( ) ;
89
89
}
90
90
91
- public async Task StartAsync ( CancellationToken cancellationToken )
91
+ public Task StartAsync ( CancellationToken cancellationToken )
92
92
{
93
- _moveFileQueue = new ActionBlock < Payload > (
94
- MoveActionHandler ,
95
- new ExecutionDataflowBlockOptions
96
- {
97
- MaxDegreeOfParallelism = _options . Value . Storage . PayloadProcessThreads ,
98
- MaxMessagesPerTask = 1 ,
99
- CancellationToken = cancellationToken
100
- } ) ;
93
+ SetupQueues ( cancellationToken ) ;
94
+
95
+ var task = Task . Run ( async ( ) =>
96
+ {
97
+ await RestoreFromDatabaseAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
98
+ BackgroundProcessing ( cancellationToken ) ;
99
+ } , CancellationToken . None ) ;
100
+
101
+ Status = ServiceStatus . Running ;
102
+ _logger . ServiceStarted ( ServiceName ) ;
103
+
104
+ if ( task . IsCompleted )
105
+ return task ;
106
+
107
+ return Task . CompletedTask ;
108
+ }
109
+
110
+ private void SetupQueues ( CancellationToken cancellationToken )
111
+ {
112
+ ResetMoveQueue ( cancellationToken ) ;
113
+ ResetPublishQueue ( cancellationToken ) ;
114
+ }
115
+
116
+ private void ResetPublishQueue ( CancellationToken cancellationToken )
117
+ {
118
+ if ( _publishQueue is not null )
119
+ {
120
+ _logger . PublishQueueFaulted ( _publishQueue . Completion . IsFaulted , _publishQueue . Completion . IsCanceled ) ;
121
+ _publishQueue . Complete ( ) ;
122
+ }
101
123
102
124
_publishQueue = new ActionBlock < Payload > (
103
125
NotificationHandler ,
@@ -107,21 +129,24 @@ public async Task StartAsync(CancellationToken cancellationToken)
107
129
MaxMessagesPerTask = 1 ,
108
130
CancellationToken = cancellationToken
109
131
} ) ;
132
+ }
110
133
111
- await RestoreFromDatabaseAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
112
-
113
- var task = Task . Run ( ( ) =>
134
+ private void ResetMoveQueue ( CancellationToken cancellationToken )
135
+ {
136
+ if ( _moveFileQueue is not null )
114
137
{
115
- BackgroundProcessing ( cancellationToken ) ;
116
- } , CancellationToken . None ) ;
117
-
118
- Status = ServiceStatus . Running ;
119
- _logger . ServiceStarted ( ServiceName ) ;
120
-
121
- if ( task . IsCompleted )
122
- await task . ConfigureAwait ( false ) ;
138
+ _logger . MoveQueueFaulted ( _moveFileQueue . Completion . IsFaulted , _moveFileQueue . Completion . IsCanceled ) ;
139
+ _moveFileQueue . Complete ( ) ;
140
+ }
123
141
124
- await Task . CompletedTask . ConfigureAwait ( false ) ;
142
+ _moveFileQueue = new ActionBlock < Payload > (
143
+ MoveActionHandler ,
144
+ new ExecutionDataflowBlockOptions
145
+ {
146
+ MaxDegreeOfParallelism = _options . Value . Storage . PayloadProcessThreads ,
147
+ MaxMessagesPerTask = 1 ,
148
+ CancellationToken = cancellationToken
149
+ } ) ;
125
150
}
126
151
127
152
private async Task NotificationHandler ( Payload payload )
@@ -134,6 +159,10 @@ private async Task NotificationHandler(Payload payload)
134
159
{
135
160
await _payloadNotificationActionHandler . NotifyAsync ( payload , _publishQueue , _cancellationTokenSource . Token ) . ConfigureAwait ( false ) ;
136
161
}
162
+ catch ( PostPayloadException ex )
163
+ {
164
+ HandlePostPayloadException ( ex ) ;
165
+ }
137
166
catch ( Exception ex )
138
167
{
139
168
if ( ex is PayloadNotifyException payloadMoveException &&
@@ -158,6 +187,10 @@ private async Task MoveActionHandler(Payload payload)
158
187
{
159
188
await _payloadMoveActionHandler . MoveFilesAsync ( payload , _moveFileQueue , _publishQueue , _cancellationTokenSource . Token ) . ConfigureAwait ( false ) ;
160
189
}
190
+ catch ( PostPayloadException ex )
191
+ {
192
+ HandlePostPayloadException ( ex ) ;
193
+ }
161
194
catch ( Exception ex )
162
195
{
163
196
if ( ex is PayloadNotifyException payloadMoveException &&
@@ -172,17 +205,45 @@ private async Task MoveActionHandler(Payload payload)
172
205
}
173
206
}
174
207
208
+ private void HandlePostPayloadException ( PostPayloadException ex )
209
+ {
210
+ Guard . Against . Null ( ex ) ;
211
+
212
+ if ( ex . TargetQueue == Payload . PayloadState . Move )
213
+ {
214
+ ResetIfFaultedOrCancelled ( _moveFileQueue , ResetMoveQueue , CancellationToken . None ) ;
215
+ if ( ! _moveFileQueue . Post ( ex . Payload ) )
216
+ {
217
+ _logger . ErrorPostingJobToMovePayloadsQueue ( ) ;
218
+ }
219
+ }
220
+ else if ( ex . TargetQueue == Payload . PayloadState . Notify )
221
+ {
222
+ ResetIfFaultedOrCancelled ( _publishQueue , ResetPublishQueue , CancellationToken . None ) ;
223
+ if ( ! _publishQueue . Post ( ex . Payload ) )
224
+ {
225
+ _logger . ErrorPostingJobToPublishPayloadsQueue ( ) ;
226
+ }
227
+ }
228
+ }
229
+
175
230
private void BackgroundProcessing ( CancellationToken cancellationToken )
176
231
{
177
232
_logger . ServiceRunning ( ServiceName ) ;
178
233
179
234
while ( ! cancellationToken . IsCancellationRequested )
180
235
{
236
+ ResetIfFaultedOrCancelled ( _moveFileQueue , ResetMoveQueue , cancellationToken ) ;
237
+ ResetIfFaultedOrCancelled ( _publishQueue , ResetPublishQueue , cancellationToken ) ;
238
+
181
239
Payload payload = null ;
182
240
try
183
241
{
184
242
payload = _payloadAssembler . Dequeue ( cancellationToken ) ;
185
- _moveFileQueue . Post ( payload ) ;
243
+ while ( ! _moveFileQueue . Post ( payload ) )
244
+ {
245
+ ResetIfFaultedOrCancelled ( _moveFileQueue , ResetMoveQueue , cancellationToken ) ;
246
+ }
186
247
_logger . PayloadQueuedForProcessing ( payload . PayloadId , ServiceName ) ;
187
248
}
188
249
catch ( OperationCanceledException ex )
@@ -202,6 +263,18 @@ private void BackgroundProcessing(CancellationToken cancellationToken)
202
263
_logger . ServiceCancelled ( ServiceName ) ;
203
264
}
204
265
266
+ private static void ResetIfFaultedOrCancelled ( ActionBlock < Payload > queue , Action < CancellationToken > resetFunction , CancellationToken cancellationToken )
267
+ {
268
+ Guard . Against . Null ( queue ) ;
269
+ Guard . Against . Null ( resetFunction ) ;
270
+
271
+ if ( queue . Completion . IsCanceledOrFaulted ( ) )
272
+ {
273
+ resetFunction ( cancellationToken ) ;
274
+ }
275
+ }
276
+
277
+
205
278
private async Task RestoreFromDatabaseAsync ( CancellationToken cancellationToken )
206
279
{
207
280
_logger . StartupRestoreFromDatabase ( ) ;
@@ -214,11 +287,17 @@ private async Task RestoreFromDatabaseAsync(CancellationToken cancellationToken)
214
287
{
215
288
if ( payload . State == Payload . PayloadState . Move )
216
289
{
217
- _moveFileQueue . Post ( payload ) ;
290
+ if ( ! _moveFileQueue . Post ( payload ) )
291
+ {
292
+ _logger . ErrorPostingJobToMovePayloadsQueue ( ) ;
293
+ }
218
294
}
219
295
else if ( payload . State == Payload . PayloadState . Notify )
220
296
{
221
- _publishQueue . Post ( payload ) ;
297
+ if ( ! _publishQueue . Post ( payload ) )
298
+ {
299
+ _logger . ErrorPostingJobToPublishPayloadsQueue ( ) ;
300
+ }
222
301
}
223
302
}
224
303
_logger . RestoredFromDatabase ( payloads . Count ) ;
0 commit comments