7
7
using Microsoft . AspNetCore . Hosting ;
8
8
using Microsoft . Azure . WebJobs . Host ;
9
9
using Microsoft . Azure . WebJobs . Host . Timers ;
10
+ using Microsoft . Azure . WebJobs . Script . Workers ;
10
11
using Microsoft . Extensions . Logging ;
11
12
12
13
namespace Microsoft . Azure . WebJobs . Script . WebHost
@@ -15,10 +16,12 @@ public class WebScriptHostExceptionHandler : IWebJobsExceptionHandler
15
16
{
16
17
private readonly IApplicationLifetime _applicationLifetime ;
17
18
private readonly ILogger _logger ;
19
+ private readonly IFunctionInvocationDispatcherFactory _functionInvocationDispatcherFactory ;
18
20
19
- public WebScriptHostExceptionHandler ( IApplicationLifetime applicationLifetime , ILogger < WebScriptHostExceptionHandler > logger )
21
+ public WebScriptHostExceptionHandler ( IApplicationLifetime applicationLifetime , ILogger < WebScriptHostExceptionHandler > logger , IFunctionInvocationDispatcherFactory functionInvocationDispatcherFactory )
20
22
{
21
23
_applicationLifetime = applicationLifetime ?? throw new ArgumentNullException ( nameof ( applicationLifetime ) ) ;
24
+ _functionInvocationDispatcherFactory = functionInvocationDispatcherFactory ;
22
25
_logger = logger ?? throw new ArgumentNullException ( nameof ( logger ) ) ;
23
26
}
24
27
@@ -39,17 +42,30 @@ public async Task OnTimeoutExceptionAsync(ExceptionDispatchInfo exceptionInfo, T
39
42
}
40
43
}
41
44
42
- LogErrorAndFlush ( "A function timeout has occurred. Host is shutting down." , exceptionInfo . SourceException ) ;
43
-
44
45
// We can't wait on this as it may cause a deadlock if the timeout was fired
45
46
// by a Listener that cannot stop until it has completed.
46
47
// TODO: DI (FACAVAL) The shutdown call will invoke the host stop... but we may need to do this
47
48
// explicitly in order to pass the timeout.
48
49
// Task ignoreTask = _hostManager.StopAsync();
49
50
// Give the manager and all running tasks some time to shut down gracefully.
50
51
//await Task.Delay(timeoutGracePeriod);
51
-
52
- _applicationLifetime . StopApplication ( ) ;
52
+ IFunctionInvocationDispatcher functionInvocationDispatcher = _functionInvocationDispatcherFactory . GetFunctionDispatcher ( ) ;
53
+ if ( functionInvocationDispatcher . State . Equals ( FunctionInvocationDispatcherState . Initialized ) )
54
+ {
55
+ _logger . LogWarning ( $ "A function timeout has occurred. Restarting worker process executing invocationId '{ timeoutException . InstanceId } '.", exceptionInfo . SourceException ) ;
56
+ bool result = await functionInvocationDispatcher . RestartWorkerWithInvocationIdAsync ( timeoutException . InstanceId . ToString ( ) ) ;
57
+ if ( ! result )
58
+ {
59
+ _logger . LogWarning ( $ "Restarting all language worker processes since invocation Id '{ timeoutException . InstanceId } ' was not found.", exceptionInfo . SourceException ) ;
60
+ await functionInvocationDispatcher . RestartAllWorkersAsync ( ) ;
61
+ }
62
+ _logger . LogWarning ( "Restart of language worker process(es) completed." , exceptionInfo . SourceException ) ;
63
+ }
64
+ else
65
+ {
66
+ LogErrorAndFlush ( "A function timeout has occurred. Host is shutting down." , exceptionInfo . SourceException ) ;
67
+ _applicationLifetime . StopApplication ( ) ;
68
+ }
53
69
}
54
70
55
71
public Task OnUnhandledExceptionAsync ( ExceptionDispatchInfo exceptionInfo )
0 commit comments