#23 - Implement graceful shutdown.
This commit is contained in:
parent
a2fd1e1d90
commit
43ae61f7bc
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Hosting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Allows consumers to perform cleanup during a graceful shutdown.
|
||||||
|
/// </summary>
|
||||||
|
public class ApplicationLifetime : IApplicationLifetime
|
||||||
|
{
|
||||||
|
private readonly CancellationTokenSource _stoppingSource = new CancellationTokenSource();
|
||||||
|
private readonly CancellationTokenSource _stoppedSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
public ApplicationLifetime()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when the application host is performing a graceful shutdown.
|
||||||
|
/// Request may still be in flight. Shutdown will block until this event completes.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public CancellationToken ApplicationStopping
|
||||||
|
{
|
||||||
|
get { return _stoppingSource.Token; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when the application host is performing a graceful shutdown.
|
||||||
|
/// All requests should be complete at this point. Shutdown will block
|
||||||
|
/// until this event completes.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public CancellationToken ApplicationStopped
|
||||||
|
{
|
||||||
|
get { return _stoppedSource.Token; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signals the ApplicationStopping event and blocks until it completes.
|
||||||
|
/// </summary>
|
||||||
|
public void SignalStopping()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_stoppingSource.Cancel(throwOnFirstException: false);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// TODO: LOG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signals the ApplicationStopped event and blocks until it completes.
|
||||||
|
/// </summary>
|
||||||
|
public void SignalStopped()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_stoppedSource.Cancel(throwOnFirstException: false);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// TODO: LOG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
{
|
{
|
||||||
public IServiceProvider Services { get; set; }
|
public IServiceProvider Services { get; set; }
|
||||||
public IConfiguration Configuration { get; set; }
|
public IConfiguration Configuration { get; set; }
|
||||||
|
public ApplicationLifetime Lifetime { get; set; }
|
||||||
|
|
||||||
public IBuilder Builder { get; set; }
|
public IBuilder Builder { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ using Microsoft.AspNet.Hosting.Builder;
|
||||||
using Microsoft.AspNet.Hosting.Server;
|
using Microsoft.AspNet.Hosting.Server;
|
||||||
using Microsoft.AspNet.Hosting.Startup;
|
using Microsoft.AspNet.Hosting.Startup;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting
|
namespace Microsoft.AspNet.Hosting
|
||||||
{
|
{
|
||||||
|
|
@ -45,6 +46,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
|
|
||||||
public IDisposable Start(HostingContext context)
|
public IDisposable Start(HostingContext context)
|
||||||
{
|
{
|
||||||
|
EnsureLifetime(context);
|
||||||
EnsureBuilder(context);
|
EnsureBuilder(context);
|
||||||
EnsureServerFactory(context);
|
EnsureServerFactory(context);
|
||||||
InitalizeServerFactory(context);
|
InitalizeServerFactory(context);
|
||||||
|
|
@ -55,11 +57,24 @@ namespace Microsoft.AspNet.Hosting
|
||||||
|
|
||||||
return new Disposable(() =>
|
return new Disposable(() =>
|
||||||
{
|
{
|
||||||
|
context.Lifetime.SignalStopping();
|
||||||
server.Dispose();
|
server.Dispose();
|
||||||
|
context.Lifetime.SignalStopped();
|
||||||
pipeline.Dispose();
|
pipeline.Dispose();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EnsureLifetime(HostingContext context)
|
||||||
|
{
|
||||||
|
if (context.Lifetime == null)
|
||||||
|
{
|
||||||
|
context.Lifetime = new ApplicationLifetime();
|
||||||
|
}
|
||||||
|
var serviceCollection = new ServiceCollection();
|
||||||
|
serviceCollection.AddInstance<IApplicationLifetime>(context.Lifetime);
|
||||||
|
context.Services = serviceCollection.BuildServiceProvider(context.Services);
|
||||||
|
}
|
||||||
|
|
||||||
private void EnsureBuilder(HostingContext context)
|
private void EnsureBuilder(HostingContext context)
|
||||||
{
|
{
|
||||||
if (context.Builder != null)
|
if (context.Builder != null)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Framework.Runtime;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Hosting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Allows consumers to perform cleanup during a graceful shutdown.
|
||||||
|
/// </summary>
|
||||||
|
[AssemblyNeutral]
|
||||||
|
public interface IApplicationLifetime
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when the application host is performing a graceful shutdown.
|
||||||
|
/// Request may still be in flight. Shutdown will block until this event completes.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
CancellationToken ApplicationStopping { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when the application host is performing a graceful shutdown.
|
||||||
|
/// All requests should be complete at this point. Shutdown will block
|
||||||
|
/// until this event completes.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
CancellationToken ApplicationStopped { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
<Content Include="project.json" />
|
<Content Include="project.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="ApplicationLifetime.cs" />
|
||||||
<Compile Include="Builder\BuilderFactory.cs" />
|
<Compile Include="Builder\BuilderFactory.cs" />
|
||||||
<Compile Include="Builder\HttpContextFactory.cs" />
|
<Compile Include="Builder\HttpContextFactory.cs" />
|
||||||
<Compile Include="Builder\IBuilderFactory.cs" />
|
<Compile Include="Builder\IBuilderFactory.cs" />
|
||||||
|
|
@ -27,6 +28,7 @@
|
||||||
<Compile Include="HostingContext.cs" />
|
<Compile Include="HostingContext.cs" />
|
||||||
<Compile Include="HostingEngine.cs" />
|
<Compile Include="HostingEngine.cs" />
|
||||||
<Compile Include="HostingServices.cs" />
|
<Compile Include="HostingServices.cs" />
|
||||||
|
<Compile Include="IApplicationLifetime.cs" />
|
||||||
<Compile Include="IHostingEngine.cs" />
|
<Compile Include="IHostingEngine.cs" />
|
||||||
<Compile Include="PipelineInstance.cs" />
|
<Compile Include="PipelineInstance.cs" />
|
||||||
<Compile Include="PlatformHelper.cs" />
|
<Compile Include="PlatformHelper.cs" />
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Framework.ConfigurationModel;
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
|
|
@ -67,11 +69,29 @@ namespace Microsoft.AspNet.Hosting
|
||||||
throw new Exception("TODO: IHostingEngine service not available exception");
|
throw new Exception("TODO: IHostingEngine service not available exception");
|
||||||
}
|
}
|
||||||
|
|
||||||
using (engine.Start(context))
|
var appShutdownService = _serviceProvider.GetService<IApplicationShutdown>();
|
||||||
|
if (appShutdownService == null)
|
||||||
|
{
|
||||||
|
throw new Exception("TODO: IApplicationShutdown service not available");
|
||||||
|
}
|
||||||
|
var shutdownHandle = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
var serverShutdown = engine.Start(context);
|
||||||
|
|
||||||
|
appShutdownService.ShutdownRequested.Register(() =>
|
||||||
|
{
|
||||||
|
serverShutdown.Dispose();
|
||||||
|
shutdownHandle.Set();
|
||||||
|
});
|
||||||
|
|
||||||
|
Task ignored = Task.Run(() =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("Started");
|
Console.WriteLine("Started");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
}
|
appShutdownService.RequestShutdown();
|
||||||
|
});
|
||||||
|
|
||||||
|
shutdownHandle.WaitOne();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue