1717 using ServiceControl . Infrastructure . Metrics ;
1818 using Transports ;
1919
20- class AuditIngestion : IHostedService
20+ class AuditIngestion : BackgroundService
2121 {
2222 static readonly long FrequencyInMilliseconds = Stopwatch . Frequency / 1000 ;
2323
@@ -70,26 +70,6 @@ public AuditIngestion(
7070 ) ;
7171 }
7272
73- public async Task StartAsync ( CancellationToken cancellationToken )
74- {
75- stopSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
76- ingestionWorker = Task . Run ( ( ) => Loop ( stopSource . Token ) , stopSource . Token ) ;
77- await watchdog . Start ( ( ) => applicationLifetime . StopApplication ( ) ) ;
78- }
79-
80- public async Task StopAsync ( CancellationToken cancellationToken )
81- {
82- await stopSource . CancelAsync ( ) ;
83- await watchdog . Stop ( ) ;
84- channel . Writer . Complete ( ) ;
85- await ingestionWorker ;
86-
87- if ( transportInfrastructure != null )
88- {
89- await transportInfrastructure . Shutdown ( cancellationToken ) ;
90- }
91- }
92-
9373 Task OnCriticalError ( string failure , Exception exception )
9474 {
9575 logger . Fatal ( $ "OnCriticalError. '{ failure } '", exception ) ;
@@ -214,13 +194,16 @@ async Task OnMessage(MessageContext messageContext, CancellationToken cancellati
214194 await taskCompletionSource . Task ;
215195 }
216196
217- async Task Loop ( CancellationToken cancellationToken )
197+
198+ protected override async Task ExecuteAsync ( CancellationToken stoppingToken )
218199 {
200+ await watchdog . Start ( ( ) => applicationLifetime . StopApplication ( ) ) ;
201+
219202 try
220203 {
221204 var contexts = new List < MessageContext > ( transportSettings . MaxConcurrency . Value ) ;
222205
223- while ( await channel . Reader . WaitToReadAsync ( cancellationToken ) )
206+ while ( await channel . Reader . WaitToReadAsync ( stoppingToken ) )
224207 {
225208 // will only enter here if there is something to read.
226209 try
@@ -237,7 +220,7 @@ async Task Loop(CancellationToken cancellationToken)
237220 await auditIngestor . Ingest ( contexts ) ;
238221 }
239222 }
240- catch ( OperationCanceledException ) when ( cancellationToken . IsCancellationRequested )
223+ catch ( OperationCanceledException ) when ( stoppingToken . IsCancellationRequested )
241224 {
242225 throw ; // Catch again in outer catch
243226 }
@@ -258,16 +241,26 @@ async Task Loop(CancellationToken cancellationToken)
258241 }
259242 // will fall out here when writer is completed
260243 }
261- catch ( OperationCanceledException ) when ( cancellationToken . IsCancellationRequested )
244+ catch ( OperationCanceledException ) when ( stoppingToken . IsCancellationRequested )
262245 {
263246 // Cancellation
264247 }
248+ finally
249+ {
250+ await watchdog . Stop ( ) ;
251+ channel . Writer . Complete ( ) ;
252+
253+ if ( transportInfrastructure != null )
254+ {
255+ // stoppingToken is cancelled, invoke so transport infrastructure will run teardown
256+ // No need to await, as this will throw OperationCancelledException
257+ _ = transportInfrastructure . Shutdown ( stoppingToken ) ;
258+ }
259+ }
265260 }
266261
267262 TransportInfrastructure transportInfrastructure ;
268263 IMessageReceiver queueIngestor ;
269- Task ingestionWorker ;
270- CancellationTokenSource stopSource ;
271264
272265 readonly SemaphoreSlim startStopSemaphore = new SemaphoreSlim ( 1 ) ;
273266 readonly string inputEndpoint ;
0 commit comments