6
6
using System . Reactive . Linq ;
7
7
using System . Threading ;
8
8
using System . Threading . Tasks ;
9
+ using Microsoft . AspNetCore . Hosting ;
9
10
using Microsoft . Azure . WebJobs . Script . Rpc ;
10
11
using Microsoft . Azure . WebJobs . Script . WebHost . Properties ;
11
12
using Microsoft . Extensions . Configuration ;
@@ -32,20 +33,21 @@ public class StandbyManager : IStandbyManager, IDisposable
32
33
private readonly HostNameProvider _hostNameProvider ;
33
34
private readonly IDisposable _changeTokenCallbackSubscription ;
34
35
private readonly TimeSpan _specializationTimerInterval ;
36
+ private readonly IApplicationLifetime _applicationLifetime ;
35
37
36
38
private Timer _specializationTimer ;
37
39
private static CancellationTokenSource _standbyCancellationTokenSource = new CancellationTokenSource ( ) ;
38
40
private static IChangeToken _standbyChangeToken = new CancellationChangeToken ( _standbyCancellationTokenSource . Token ) ;
39
41
private static SemaphoreSlim _semaphore = new SemaphoreSlim ( 1 , 1 ) ;
40
42
41
43
public StandbyManager ( IScriptHostManager scriptHostManager , IWebHostLanguageWorkerChannelManager languageWorkerChannelManager , IConfiguration configuration , IScriptWebHostEnvironment webHostEnvironment ,
42
- IEnvironment environment , IOptionsMonitor < ScriptApplicationHostOptions > options , ILogger < StandbyManager > logger , HostNameProvider hostNameProvider )
43
- : this ( scriptHostManager , languageWorkerChannelManager , configuration , webHostEnvironment , environment , options , logger , hostNameProvider , TimeSpan . FromMilliseconds ( 500 ) )
44
+ IEnvironment environment , IOptionsMonitor < ScriptApplicationHostOptions > options , ILogger < StandbyManager > logger , HostNameProvider hostNameProvider , IApplicationLifetime applicationLifetime )
45
+ : this ( scriptHostManager , languageWorkerChannelManager , configuration , webHostEnvironment , environment , options , logger , hostNameProvider , applicationLifetime , TimeSpan . FromMilliseconds ( 500 ) )
44
46
{
45
47
}
46
48
47
49
public StandbyManager ( IScriptHostManager scriptHostManager , IWebHostLanguageWorkerChannelManager languageWorkerChannelManager , IConfiguration configuration , IScriptWebHostEnvironment webHostEnvironment ,
48
- IEnvironment environment , IOptionsMonitor < ScriptApplicationHostOptions > options , ILogger < StandbyManager > logger , HostNameProvider hostNameProvider , TimeSpan specializationTimerInterval )
50
+ IEnvironment environment , IOptionsMonitor < ScriptApplicationHostOptions > options , ILogger < StandbyManager > logger , HostNameProvider hostNameProvider , IApplicationLifetime applicationLifetime , TimeSpan specializationTimerInterval )
49
51
{
50
52
_scriptHostManager = scriptHostManager ?? throw new ArgumentNullException ( nameof ( scriptHostManager ) ) ;
51
53
_options = options ?? throw new ArgumentNullException ( nameof ( options ) ) ;
@@ -58,13 +60,23 @@ public StandbyManager(IScriptHostManager scriptHostManager, IWebHostLanguageWork
58
60
_hostNameProvider = hostNameProvider ?? throw new ArgumentNullException ( nameof ( hostNameProvider ) ) ;
59
61
_changeTokenCallbackSubscription = ChangeToken . RegisterChangeCallback ( _ => _logger . LogDebug ( $ "{ nameof ( StandbyManager ) } .{ nameof ( ChangeToken ) } callback has fired.") , null ) ;
60
62
_specializationTimerInterval = specializationTimerInterval ;
63
+ _applicationLifetime = applicationLifetime ;
61
64
}
62
65
63
66
public static IChangeToken ChangeToken => _standbyChangeToken ;
64
67
65
68
public Task SpecializeHostAsync ( )
66
69
{
67
- return _specializationTask . Value ;
70
+ return _specializationTask . Value . ContinueWith ( t =>
71
+ {
72
+ if ( t . IsFaulted )
73
+ {
74
+ // if we fail during specialization for whatever reason
75
+ // this is fatal, so we shutdown
76
+ _logger . LogError ( t . Exception , $ "Specialization failed. Shutting down.") ;
77
+ _applicationLifetime . StopApplication ( ) ;
78
+ }
79
+ } ) ;
68
80
}
69
81
70
82
public async Task SpecializeHostCoreAsync ( )
@@ -86,6 +98,7 @@ public async Task SpecializeHostCoreAsync()
86
98
_hostNameProvider . Reset ( ) ;
87
99
88
100
await _languageWorkerChannelManager . SpecializeAsync ( ) ;
101
+
89
102
NotifyChange ( ) ;
90
103
await _scriptHostManager . RestartHostAsync ( ) ;
91
104
await _scriptHostManager . DelayUntilHostReady ( ) ;
@@ -165,15 +178,14 @@ private async Task CreateStandbyWarmupFunctions()
165
178
_logger . LogInformation ( $ "StandbyMode placeholder function directory created") ;
166
179
}
167
180
168
- private void OnSpecializationTimerTick ( object state )
181
+ private async void OnSpecializationTimerTick ( object state )
169
182
{
170
183
if ( ! _webHostEnvironment . InStandbyMode && _environment . IsContainerReady ( ) )
171
184
{
172
185
_specializationTimer ? . Dispose ( ) ;
173
186
_specializationTimer = null ;
174
187
175
- SpecializeHostAsync ( ) . ContinueWith ( t => _logger . LogError ( t . Exception , "Error specializing host." ) ,
176
- TaskContinuationOptions . OnlyOnFaulted ) ;
188
+ await SpecializeHostAsync ( ) ;
177
189
}
178
190
}
179
191
0 commit comments