66using System . Reactive . Linq ;
77using System . Threading ;
88using System . Threading . Tasks ;
9+ using Microsoft . AspNetCore . Hosting ;
910using Microsoft . Azure . WebJobs . Script . Rpc ;
1011using Microsoft . Azure . WebJobs . Script . WebHost . Properties ;
1112using Microsoft . Extensions . Configuration ;
@@ -32,20 +33,21 @@ public class StandbyManager : IStandbyManager, IDisposable
3233 private readonly HostNameProvider _hostNameProvider ;
3334 private readonly IDisposable _changeTokenCallbackSubscription ;
3435 private readonly TimeSpan _specializationTimerInterval ;
36+ private readonly IApplicationLifetime _applicationLifetime ;
3537
3638 private Timer _specializationTimer ;
3739 private static CancellationTokenSource _standbyCancellationTokenSource = new CancellationTokenSource ( ) ;
3840 private static IChangeToken _standbyChangeToken = new CancellationChangeToken ( _standbyCancellationTokenSource . Token ) ;
3941 private static SemaphoreSlim _semaphore = new SemaphoreSlim ( 1 , 1 ) ;
4042
4143 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 ) )
4446 {
4547 }
4648
4749 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 )
4951 {
5052 _scriptHostManager = scriptHostManager ?? throw new ArgumentNullException ( nameof ( scriptHostManager ) ) ;
5153 _options = options ?? throw new ArgumentNullException ( nameof ( options ) ) ;
@@ -58,13 +60,23 @@ public StandbyManager(IScriptHostManager scriptHostManager, IWebHostLanguageWork
5860 _hostNameProvider = hostNameProvider ?? throw new ArgumentNullException ( nameof ( hostNameProvider ) ) ;
5961 _changeTokenCallbackSubscription = ChangeToken . RegisterChangeCallback ( _ => _logger . LogDebug ( $ "{ nameof ( StandbyManager ) } .{ nameof ( ChangeToken ) } callback has fired.") , null ) ;
6062 _specializationTimerInterval = specializationTimerInterval ;
63+ _applicationLifetime = applicationLifetime ;
6164 }
6265
6366 public static IChangeToken ChangeToken => _standbyChangeToken ;
6467
6568 public Task SpecializeHostAsync ( )
6669 {
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+ } ) ;
6880 }
6981
7082 public async Task SpecializeHostCoreAsync ( )
@@ -86,6 +98,7 @@ public async Task SpecializeHostCoreAsync()
8698 _hostNameProvider . Reset ( ) ;
8799
88100 await _languageWorkerChannelManager . SpecializeAsync ( ) ;
101+
89102 NotifyChange ( ) ;
90103 await _scriptHostManager . RestartHostAsync ( ) ;
91104 await _scriptHostManager . DelayUntilHostReady ( ) ;
@@ -165,15 +178,14 @@ private async Task CreateStandbyWarmupFunctions()
165178 _logger . LogInformation ( $ "StandbyMode placeholder function directory created") ;
166179 }
167180
168- private void OnSpecializationTimerTick ( object state )
181+ private async void OnSpecializationTimerTick ( object state )
169182 {
170183 if ( ! _webHostEnvironment . InStandbyMode && _environment . IsContainerReady ( ) )
171184 {
172185 _specializationTimer ? . Dispose ( ) ;
173186 _specializationTimer = null ;
174187
175- SpecializeHostAsync ( ) . ContinueWith ( t => _logger . LogError ( t . Exception , "Error specializing host." ) ,
176- TaskContinuationOptions . OnlyOnFaulted ) ;
188+ await SpecializeHostAsync ( ) ;
177189 }
178190 }
179191
0 commit comments