17
17
using ServiceControl . Infrastructure . Metrics ;
18
18
using Transports ;
19
19
20
- class AuditIngestion : IHostedService
20
+ class AuditIngestion : BackgroundService
21
21
{
22
22
static readonly long FrequencyInMilliseconds = Stopwatch . Frequency / 1000 ;
23
23
@@ -59,23 +59,15 @@ public AuditIngestion(
59
59
60
60
errorHandlingPolicy = new AuditIngestionFaultPolicy ( failedImportsStorage , settings . LoggingSettings , OnCriticalError ) ;
61
61
62
- watchdog = new Watchdog ( "audit message ingestion" , EnsureStarted , EnsureStopped , ingestionState . ReportError , ingestionState . Clear , settings . TimeToRestartAuditIngestionAfterFailure , logger ) ;
63
-
64
- ingestionWorker = Task . Run ( ( ) => Loop ( ) , CancellationToken . None ) ;
65
- }
66
-
67
- public Task StartAsync ( CancellationToken _ ) => watchdog . Start ( ( ) => applicationLifetime . StopApplication ( ) ) ;
68
-
69
- public async Task StopAsync ( CancellationToken cancellationToken )
70
- {
71
- await watchdog . Stop ( ) ;
72
- channel . Writer . Complete ( ) ;
73
- await ingestionWorker ;
74
-
75
- if ( transportInfrastructure != null )
76
- {
77
- await transportInfrastructure . Shutdown ( cancellationToken ) ;
78
- }
62
+ watchdog = new Watchdog (
63
+ "audit message ingestion" ,
64
+ EnsureStarted ,
65
+ EnsureStopped ,
66
+ ingestionState . ReportError ,
67
+ ingestionState . Clear ,
68
+ settings . TimeToRestartAuditIngestionAfterFailure ,
69
+ logger
70
+ ) ;
79
71
}
80
72
81
73
Task OnCriticalError ( string failure , Exception exception )
@@ -139,7 +131,7 @@ async Task EnsureStarted(CancellationToken cancellationToken = default)
139
131
}
140
132
catch ( OperationCanceledException e ) when ( e . CancellationToken == cancellationToken )
141
133
{
142
- // ignored
134
+ logger . Info ( "StopReceive cancelled" ) ;
143
135
}
144
136
}
145
137
@@ -176,7 +168,7 @@ async Task EnsureStopped(CancellationToken cancellationToken = default)
176
168
}
177
169
catch ( OperationCanceledException e ) when ( e . CancellationToken == cancellationToken )
178
170
{
179
- // ignored
171
+ logger . Info ( "StopReceive cancelled" ) ;
180
172
}
181
173
finally
182
174
{
@@ -202,51 +194,86 @@ async Task OnMessage(MessageContext messageContext, CancellationToken cancellati
202
194
await taskCompletionSource . Task ;
203
195
}
204
196
205
- async Task Loop ( )
197
+ public override async Task StartAsync ( CancellationToken cancellationToken )
206
198
{
207
- var contexts = new List < MessageContext > ( transportSettings . MaxConcurrency . Value ) ;
199
+ await watchdog . Start ( ( ) => applicationLifetime . StopApplication ( ) ) ;
200
+ await base . StartAsync ( cancellationToken ) ;
201
+ }
208
202
209
- while ( await channel . Reader . WaitToReadAsync ( ) )
203
+ protected override async Task ExecuteAsync ( CancellationToken stoppingToken )
204
+ {
205
+ try
210
206
{
211
- // will only enter here if there is something to read.
212
- try
207
+ var contexts = new List < MessageContext > ( transportSettings . MaxConcurrency . Value ) ;
208
+
209
+ while ( await channel . Reader . WaitToReadAsync ( stoppingToken ) )
213
210
{
214
- // as long as there is something to read this will fetch up to MaximumConcurrency items
215
- while ( channel . Reader . TryRead ( out var context ) )
211
+ // will only enter here if there is something to read.
212
+ try
216
213
{
217
- contexts . Add ( context ) ;
214
+ // as long as there is something to read this will fetch up to MaximumConcurrency items
215
+ while ( channel . Reader . TryRead ( out var context ) )
216
+ {
217
+ contexts . Add ( context ) ;
218
+ }
219
+
220
+ batchSizeMeter . Mark ( contexts . Count ) ;
221
+ using ( batchDurationMeter . Measure ( ) )
222
+ {
223
+ await auditIngestor . Ingest ( contexts ) ;
224
+ }
218
225
}
226
+ catch ( Exception e )
227
+ {
228
+ // signal all message handling tasks to terminate
229
+ foreach ( var context in contexts )
230
+ {
231
+ _ = context . GetTaskCompletionSource ( ) . TrySetException ( e ) ;
232
+ }
233
+
234
+ if ( e is OperationCanceledException && stoppingToken . IsCancellationRequested )
235
+ {
236
+ logger . Info ( "Batch cancelled" , e ) ;
237
+ break ;
238
+ }
219
239
220
- batchSizeMeter . Mark ( contexts . Count ) ;
221
- using ( batchDurationMeter . Measure ( ) )
240
+ logger . Info ( "Ingesting messages failed" , e ) ;
241
+ }
242
+ finally
222
243
{
223
- await auditIngestor . Ingest ( contexts ) ;
244
+ contexts . Clear ( ) ;
224
245
}
225
246
}
226
- catch ( OperationCanceledException )
227
- {
228
- //Do nothing as we are shutting down
229
- continue ;
230
- }
231
- catch ( Exception e ) // show must go on
247
+ // will fall out here when writer is completed
248
+ }
249
+ catch ( OperationCanceledException ) when ( stoppingToken . IsCancellationRequested )
250
+ {
251
+ // ExecuteAsync cancelled
252
+ }
253
+ }
254
+
255
+ public override async Task StopAsync ( CancellationToken cancellationToken )
256
+ {
257
+ try
258
+ {
259
+ await watchdog . Stop ( ) ;
260
+ channel . Writer . Complete ( ) ;
261
+ await base . StopAsync ( cancellationToken ) ;
262
+ }
263
+ finally
264
+ {
265
+ if ( transportInfrastructure != null )
232
266
{
233
- if ( logger . IsInfoEnabled )
267
+ try
234
268
{
235
- logger . Info ( "Ingesting messages failed" , e ) ;
269
+ await transportInfrastructure . Shutdown ( cancellationToken ) ;
236
270
}
237
-
238
- // signal all message handling tasks to terminate
239
- foreach ( var context in contexts )
271
+ catch ( OperationCanceledException e ) when ( cancellationToken . IsCancellationRequested )
240
272
{
241
- context . GetTaskCompletionSource ( ) . TrySetException ( e ) ;
273
+ logger . Info ( "Shutdown cancelled" , e ) ;
242
274
}
243
275
}
244
- finally
245
- {
246
- contexts . Clear ( ) ;
247
- }
248
276
}
249
- // will fall out here when writer is completed
250
277
}
251
278
252
279
TransportInfrastructure transportInfrastructure ;
@@ -265,7 +292,6 @@ async Task Loop()
265
292
readonly Meter batchDurationMeter ;
266
293
readonly Counter receivedMeter ;
267
294
readonly Watchdog watchdog ;
268
- readonly Task ingestionWorker ;
269
295
readonly IHostApplicationLifetime applicationLifetime ;
270
296
271
297
static readonly ILog logger = LogManager . GetLogger < AuditIngestion > ( ) ;
0 commit comments