Azure / Azure/azure-functions-dotnet-worker

Out of process worker ignores shutdown timeout through HostOptions and IHostedLifecycleService

Open
#2,667 4 comments 0 reactions 1 assignee Claimed by @liliankasem View on GitHub
area: migration needs-investigation
Dominant language
C#
Stars
466
Forks
215
Avg merge
3d 10h
Merged PRs (30d)
7

Description

### What version of .NET does your existing project use?

.NET 6

### What version of .NET are you attempting to target?

.NET 8

### Description

We've got a project using durable functions, and we are having an interesting time trying to delay worker shutdown by longer than the default of ~5? ~30? seconds. I suspect this is because we're only configuring one half of the out of process situation, and the other process just shuts down at the default 5 second delay with no way to override it I can find.

What we see, in and out of the debugger, with both azure function tools locally and deployed to an app service:
* The methods in Shutdown do get called.
* The process exits very quickly regards of what the HostOptions is set to, or if any method in Shutdown's life cycle methods blocks.

Is there something we're doing here incorrectly, or is this even supported with isolated? I do see a startup timeout configuration for host.json, but no matching shutdown timeout one.

Program.cs:
```csharp
var settings = new ConfigurationBuilder().AddEnvironmentVariables().Build();
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(services =>
{
Startup.Setup(settings: settings, services: services);
services.AddHostedService();
services.Configure(options =>
{
options.ShutdownTimeout = TimeSpan.FromMinutes(3);
});
}).ConfigureLogging(configureLogging =>
{
// https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=windows#managing-log-levels
configureLogging.Services.Configure(options =>
{
LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
== "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
if (defaultRule is not null)
{
options.Rules.Remove(defaultRule);
}
});

// Host.json configuration only applies to host, load log filters for worker.
configureLogging.AddConfiguration(
new ConfigurationBuilder().AddJsonFile("appSettings.json").Build().GetSection("Logging"));
}).Build();
await Startup.PostSetupAsync(host);
await host.RunAsync();
```

Shutdown.cs:

```csharp
///
/// Provides methods to shutdown the worker.
///
public class Shutdown : IHostedLifecycleService
{
TaskProcessor _taskProcessor;

public Shutdown(IHostApplicationLifetime appLifetime,
BlobContainerClient blobContainerClient,
CloudTableClient tableClient,
ConfigurationRepository configurationRepository,
CosmosClient cosmosClient,
IConnectionMultiplexer redisMux,
EventProcessorClient eventProcessorClient,
EventHubProducerClient eventProducerClient,
TelemetryClient telemetryClient)
{
_taskProcessor = new TaskProcessor(
blobContainerClient: blobContainerClient,
tableClient: tableClient,
configurationRepository: configurationRepository,
cosmosClient: cosmosClient,
redisMux: redisMux,
eventProcessorClient: eventProcessorClient,
eventProducerClient: eventProducerClient,
telemetryClient: telemetryClient);

appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopping);
}

private void OnStopping()
{
Task.Run(() => StoppingAsync(CancellationToken.None).GetAwaiter().GetResult());
}
```
### Project configuration and dependencies

```xml















all
runtime; build; native; contentfiles; analyzers; buildtransitive


```

### Link to a repository that reproduces the issue

_No response_

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.