@@ -21,6 +21,7 @@ internal sealed class WorkspaceHostedService(
2121{
2222 private readonly CancellationTokenSource _cts = new ( ) ;
2323 private Task ? _connectionStatusLoop ;
24+ private Task ? _serverCredentialsLoop ;
2425 private Task ? _serverRegisteredLoop ;
2526 private bool _startupDone ;
2627
@@ -34,6 +35,7 @@ public Task StartAsync(CancellationToken cancellationToken)
3435 client . ChannelDestroyed += OnChannelDestroyedAsync ;
3536 _serverRegisteredLoop = Task . Run ( ( ) => ConsumeServerRegisteredAsync ( _cts . Token ) , CancellationToken . None ) ;
3637 _connectionStatusLoop = Task . Run ( ( ) => ConsumeConnectionStatusAsync ( _cts . Token ) , CancellationToken . None ) ;
38+ _serverCredentialsLoop = Task . Run ( ( ) => ConsumeServerCredentialsAsync ( _cts . Token ) , CancellationToken . None ) ;
3739 return Task . CompletedTask ;
3840 }
3941
@@ -45,7 +47,7 @@ public async Task StopAsync(CancellationToken cancellationToken)
4547 await _cts . CancelAsync ( ) . ConfigureAwait ( false ) ;
4648 foreach ( var loop in new [ ]
4749 {
48- _serverRegisteredLoop , _connectionStatusLoop
50+ _serverRegisteredLoop , _connectionStatusLoop , _serverCredentialsLoop
4951 } )
5052 {
5153 if ( loop is null )
@@ -136,6 +138,32 @@ await reconciler.ReconcileServerAsync(changed.GuildId, changed.ServerId, cancell
136138 }
137139 }
138140
141+ private async Task ConsumeServerCredentialsAsync ( CancellationToken cancellationToken )
142+ {
143+ try
144+ {
145+ await foreach ( var changed in eventBus . SubscribeAsync < ServerCredentialsChangedEvent > ( cancellationToken )
146+ . ConfigureAwait ( false ) )
147+ {
148+ var scope = scopeFactory . CreateAsyncScope ( ) ;
149+ await using ( scope . ConfigureAwait ( false ) )
150+ {
151+ var reconciler = scope . ServiceProvider . GetRequiredService < IWorkspaceReconciler > ( ) ;
152+ await reconciler . ReconcileServerAsync ( changed . GuildId , changed . ServerId , cancellationToken )
153+ . ConfigureAwait ( false ) ;
154+ }
155+ }
156+ }
157+ catch ( OperationCanceledException )
158+ {
159+ // Shutting down.
160+ }
161+ catch ( Exception ex ) // Broad catch is intentional: a faulting consumer must not crash the host.
162+ {
163+ logger . LogError ( ex , "ServerCredentialsChanged consumer faulted." ) ;
164+ }
165+ }
166+
139167 private async Task ConsumeServerRegisteredAsync ( CancellationToken cancellationToken )
140168 {
141169 // Subscription is registered when this loop first calls SubscribeAsync; the in-process bus does
0 commit comments