6
6
using Grpc . Core ;
7
7
using Microsoft . AspNetCore . Authorization ;
8
8
using Microsoft . Extensions . Hosting ;
9
+ using Microsoft . Extensions . Logging ;
9
10
10
11
namespace Aspire . Hosting . Dashboard ;
11
12
@@ -17,7 +18,7 @@ namespace Aspire.Hosting.Dashboard;
17
18
/// required beyond a single request. Longer-scoped data is stored in <see cref="DashboardServiceData"/>.
18
19
/// </remarks>
19
20
[ Authorize ( Policy = ResourceServiceApiKeyAuthorization . PolicyName ) ]
20
- internal sealed partial class DashboardService ( DashboardServiceData serviceData , IHostEnvironment hostEnvironment , IHostApplicationLifetime hostApplicationLifetime )
21
+ internal sealed partial class DashboardService ( DashboardServiceData serviceData , IHostEnvironment hostEnvironment , IHostApplicationLifetime hostApplicationLifetime , ILogger < DashboardService > logger )
21
22
: Aspire . ResourceService . Proto . V1 . DashboardService . DashboardServiceBase
22
23
{
23
24
// Calls that consume or produce streams must create a linked cancellation token
@@ -53,18 +54,11 @@ public override async Task WatchResources(
53
54
IServerStreamWriter < WatchResourcesUpdate > responseStream ,
54
55
ServerCallContext context )
55
56
{
56
- using var cts = CancellationTokenSource . CreateLinkedTokenSource ( hostApplicationLifetime . ApplicationStopping , context . CancellationToken ) ;
57
+ await ExecuteAsync (
58
+ WatchResourcesInternal ,
59
+ context ) . ConfigureAwait ( false ) ;
57
60
58
- try
59
- {
60
- await WatchResourcesInternal ( ) . ConfigureAwait ( false ) ;
61
- }
62
- catch ( Exception ex ) when ( ex is OperationCanceledException or IOException && cts . Token . IsCancellationRequested )
63
- {
64
- // Ignore cancellation and just return. Note that cancelled writes throw IOException.
65
- }
66
-
67
- async Task WatchResourcesInternal ( )
61
+ async Task WatchResourcesInternal ( CancellationToken cancellationToken )
68
62
{
69
63
var ( initialData , updates ) = serviceData . SubscribeResources ( ) ;
70
64
@@ -75,9 +69,9 @@ async Task WatchResourcesInternal()
75
69
data . Resources . Add ( Resource . FromSnapshot ( resource ) ) ;
76
70
}
77
71
78
- await responseStream . WriteAsync ( new ( ) { InitialData = data } ) . ConfigureAwait ( false ) ;
72
+ await responseStream . WriteAsync ( new ( ) { InitialData = data } , cancellationToken ) . ConfigureAwait ( false ) ;
79
73
80
- await foreach ( var batch in updates . WithCancellation ( cts . Token ) . ConfigureAwait ( false ) )
74
+ await foreach ( var batch in updates . WithCancellation ( cancellationToken ) . ConfigureAwait ( false ) )
81
75
{
82
76
WatchResourcesChanges changes = new ( ) ;
83
77
@@ -101,7 +95,7 @@ async Task WatchResourcesInternal()
101
95
changes . Value . Add ( change ) ;
102
96
}
103
97
104
- await responseStream . WriteAsync ( new ( ) { Changes = changes } , cts . Token ) . ConfigureAwait ( false ) ;
98
+ await responseStream . WriteAsync ( new ( ) { Changes = changes } , cancellationToken ) . ConfigureAwait ( false ) ;
105
99
}
106
100
}
107
101
}
@@ -111,18 +105,11 @@ public override async Task WatchResourceConsoleLogs(
111
105
IServerStreamWriter < WatchResourceConsoleLogsUpdate > responseStream ,
112
106
ServerCallContext context )
113
107
{
114
- using var cts = CancellationTokenSource . CreateLinkedTokenSource ( hostApplicationLifetime . ApplicationStopping , context . CancellationToken ) ;
108
+ await ExecuteAsync (
109
+ WatchResourceConsoleLogsInternal ,
110
+ context ) . ConfigureAwait ( false ) ;
115
111
116
- try
117
- {
118
- await WatchResourceConsoleLogsInternal ( ) . ConfigureAwait ( false ) ;
119
- }
120
- catch ( Exception ex ) when ( ex is OperationCanceledException or IOException && cts . Token . IsCancellationRequested )
121
- {
122
- // Ignore cancellation and just return. Note that cancelled writes throw IOException.
123
- }
124
-
125
- async Task WatchResourceConsoleLogsInternal ( )
112
+ async Task WatchResourceConsoleLogsInternal ( CancellationToken cancellationToken )
126
113
{
127
114
var subscription = serviceData . SubscribeConsoleLogs ( request . ResourceName ) ;
128
115
@@ -131,7 +118,7 @@ async Task WatchResourceConsoleLogsInternal()
131
118
return ;
132
119
}
133
120
134
- await foreach ( var group in subscription . WithCancellation ( cts . Token ) . ConfigureAwait ( false ) )
121
+ await foreach ( var group in subscription . WithCancellation ( cancellationToken ) . ConfigureAwait ( false ) )
135
122
{
136
123
var update = new WatchResourceConsoleLogsUpdate ( ) ;
137
124
@@ -140,8 +127,31 @@ async Task WatchResourceConsoleLogsInternal()
140
127
update . LogLines . Add ( new ConsoleLogLine ( ) { LineNumber = lineNumber , Text = content , IsStdErr = isErrorMessage } ) ;
141
128
}
142
129
143
- await responseStream . WriteAsync ( update , cts . Token ) . ConfigureAwait ( false ) ;
130
+ await responseStream . WriteAsync ( update , cancellationToken ) . ConfigureAwait ( false ) ;
144
131
}
145
132
}
146
133
}
134
+
135
+ private async Task ExecuteAsync ( Func < CancellationToken , Task > execute , ServerCallContext serverCallContext )
136
+ {
137
+ using var cts = CancellationTokenSource . CreateLinkedTokenSource ( hostApplicationLifetime . ApplicationStopping , serverCallContext . CancellationToken ) ;
138
+
139
+ try
140
+ {
141
+ await execute ( cts . Token ) . ConfigureAwait ( false ) ;
142
+ }
143
+ catch ( OperationCanceledException ) when ( cts . Token . IsCancellationRequested )
144
+ {
145
+ // Ignore cancellation and just return.
146
+ }
147
+ catch ( IOException ) when ( cts . Token . IsCancellationRequested )
148
+ {
149
+ // Ignore cancellation and just return. Cancelled writes throw IOException.
150
+ }
151
+ catch ( Exception ex )
152
+ {
153
+ logger . LogError ( ex , $ "Error executing service method '{ serverCallContext . Method } '.") ;
154
+ throw ;
155
+ }
156
+ }
147
157
}
0 commit comments