#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 IConfiguration Configuration { get; set; }
|
||||
public ApplicationLifetime Lifetime { 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.Startup;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting
|
||||
{
|
||||
|
|
@ -45,6 +46,7 @@ namespace Microsoft.AspNet.Hosting
|
|||
|
||||
public IDisposable Start(HostingContext context)
|
||||
{
|
||||
EnsureLifetime(context);
|
||||
EnsureBuilder(context);
|
||||
EnsureServerFactory(context);
|
||||
InitalizeServerFactory(context);
|
||||
|
|
@ -55,11 +57,24 @@ namespace Microsoft.AspNet.Hosting
|
|||
|
||||
return new Disposable(() =>
|
||||
{
|
||||
context.Lifetime.SignalStopping();
|
||||
server.Dispose();
|
||||
context.Lifetime.SignalStopped();
|
||||
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)
|
||||
{
|
||||
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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ApplicationLifetime.cs" />
|
||||
<Compile Include="Builder\BuilderFactory.cs" />
|
||||
<Compile Include="Builder\HttpContextFactory.cs" />
|
||||
<Compile Include="Builder\IBuilderFactory.cs" />
|
||||
|
|
@ -27,6 +28,7 @@
|
|||
<Compile Include="HostingContext.cs" />
|
||||
<Compile Include="HostingEngine.cs" />
|
||||
<Compile Include="HostingServices.cs" />
|
||||
<Compile Include="IApplicationLifetime.cs" />
|
||||
<Compile Include="IHostingEngine.cs" />
|
||||
<Compile Include="PipelineInstance.cs" />
|
||||
<Compile Include="PlatformHelper.cs" />
|
||||
|
|
@ -45,4 +47,4 @@
|
|||
<Compile Include="WebApplication.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Framework.ConfigurationModel;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
|
|
@ -67,11 +69,29 @@ namespace Microsoft.AspNet.Hosting
|
|||
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.ReadLine();
|
||||
}
|
||||
appShutdownService.RequestShutdown();
|
||||
});
|
||||
|
||||
shutdownHandle.WaitOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue