Check for a shutdown signal in the webjob program before initializing data

We have seen intermittent cases where a couple of devices would be
bootstrapped, then about 7 seconds later four more devices. After some
investigation we found that on every fresh cloud deploy the web job would
go through two starts -- we suspect this is as it goes through the
staging, warmup and swap to production.

To avoid letting this happen we will watch the location of the shutdown
file that is created when shutdown is scheduled. If we see that before we
enter the initialization method then we will skip initialization since it
will likely be aborted mid-process.

In Debugging we have sometimes seen cases where initialization is started,
then the shutdown signal is immediatly received. However, in these cases
initialization has been able to complete successfully.

It may not be a perfect solution, but for now I think it's pretty solid.
This commit is contained in:
Joe Rowley 2015-10-08 08:59:56 -06:00
Родитель 34bdd3767f
Коммит 3ca565624f
1 изменённых файлов: 46 добавлений и 3 удалений

Просмотреть файл

@ -21,6 +21,7 @@ using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WorkerRole
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.Configurations;
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.EventProcessor.WorkerRole.DataInitialization;
using Microsoft.Azure.IoT.Samples.EventProcessor.WorkerRole.Processors;
using System.IO;
namespace DeviceAdministration.WebJob
{
@ -31,10 +32,40 @@ namespace DeviceAdministration.WebJob
//static ManualResetEvent runCompleteEvent = new ManualResetEvent(false);
static IContainer eventProcessorContainer;
private static readonly string SHUTDOWN_FILE_ENV_VAR = "WEBJOBS_SHUTDOWN_FILE";
private static string _shutdownFile;
private static bool _shutdownSignalReceived = false;
static void Main(string[] args)
{
try
{
//Cloud deploys often get staged and started to warm them up, then get a shutdown
//signal from the framework before being moved to the production slot. We don't want
//to start initializing data if we have already gotten the shutdown message, so we'll
//monitor it. This environment variable is reliable
//http://blog.amitapple.com/post/2014/05/webjobs-graceful-shutdown/#.VhVYO6L8-B4
_shutdownFile = Environment.GetEnvironmentVariable(SHUTDOWN_FILE_ENV_VAR);
// Setup a file system watcher on that file's directory to know when the file is created
//First check for null, though. This does not exist on a localhost deploy, only cloud
if (!string.IsNullOrWhiteSpace(_shutdownFile))
{
var fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(_shutdownFile));
fileSystemWatcher.Created += OnShutdownFileChanged;
fileSystemWatcher.Changed += OnShutdownFileChanged;
fileSystemWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.LastWrite;
fileSystemWatcher.IncludeSubdirectories = false;
fileSystemWatcher.EnableRaisingEvents = true;
//In case the file had already been created before we started watching it.
if (System.IO.File.Exists(_shutdownFile))
{
_shutdownSignalReceived = true;
}
}
BuildContainer();
CreateInitialDataAsNeeded();
@ -53,6 +84,14 @@ namespace DeviceAdministration.WebJob
}
}
private static void OnShutdownFileChanged(object sender, FileSystemEventArgs e)
{
if (e.FullPath.IndexOf(Path.GetFileName(_shutdownFile), StringComparison.OrdinalIgnoreCase) >= 0)
{
_shutdownSignalReceived = true;
}
}
static void BuildContainer()
{
var builder = new ContainerBuilder();
@ -62,9 +101,13 @@ namespace DeviceAdministration.WebJob
static void CreateInitialDataAsNeeded()
{
Trace.TraceInformation("Preparing to add initial data");
var creator = eventProcessorContainer.Resolve<IDataInitializer>();
creator.CreateInitialDataIfNeeded();
if (!_shutdownSignalReceived && !cancellationTokenSource.Token.IsCancellationRequested)
{
Trace.TraceInformation("Preparing to add initial data");
var creator = eventProcessorContainer.Resolve<IDataInitializer>();
creator.CreateInitialDataIfNeeded();
}
}
static void StartEventProcessorHost()