// TODO: Needs attention as this isn't right yet - too tired!
        private Task StartTask(IComponentIdentity componentIdentity, Func<Exception, int, bool> restartEvaluator)
        {
            return Task.Factory.StartNew(() =>
            {
                int retryCount = 0;
                bool shouldRetry = true;
                while (shouldRetry)
                {
                    try
                    {
                        Task.Factory.StartNew(() =>
                        {
                            _logger.Information(String.Format("Hostable component {0} is starting", componentIdentity));
                            IHostableComponent component = _componentFactory.Create(componentIdentity);
                            component.Start(_cancellationTokenSource.Token).Wait();
                            shouldRetry = false; // normal exit
                            _logger.Information(String.Format("Hostable component {0} is exiting", componentIdentity));
                        }, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).Wait();
                        shouldRetry = false;
                    }
                    catch (Exception ex)
                    {

                        if (CustomErrorHandler != null)
                        {
                            CustomErrorHandler(ex, retryCount);
                        }

                        retryCount++;
                        shouldRetry = restartEvaluator != null && restartEvaluator(ex, retryCount);
                        if (shouldRetry)
                        {
                            _logger.Information(String.Format("Restarting {0} for component {1}", retryCount, componentIdentity), ex);
                            if (ex is AggregateException)
                            {
                                foreach (Exception innerException in ((AggregateException)ex).InnerExceptions)
                                {
                                    _logger.Error(String.Format("Aggregate error for component {1} on retry {0}", retryCount, componentIdentity), innerException);
                                }
                            }
                        }
                        else
                        {
                            if (ex is AggregateException)
                            {
                                foreach (Exception innerException in ((AggregateException) ex).InnerExceptions)
                                {
                                    _logger.Error(String.Format("Component failure {0} for component {1}", retryCount, componentIdentity), innerException);
                                }
                            }
                            else
                            {
                                _logger.Error(String.Format("Component failure {0} for component {1}", retryCount, componentIdentity), ex);
                            }
                        }
                    }
                }
                
            }, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
 private static void RestartHandler(Exception ex, int retryCount, IComponentIdentity componentIdentity)
 {
     if (retryCount%5 == 0)
     {
         Console.WriteLine("Pausing for 5 seconds");
         Thread.Sleep(TimeSpan.FromSeconds(5));
     }
 }
 public IHostableComponent Create(IComponentIdentity componentIdentity)
 {
     try
     {
         return _container.Resolve<IHostableComponent>(componentIdentity.ToString());
     }
     catch (Exception)
     {
         return null;
     }
 }
 protected AbstractApplicationComponent()
 {
     try
     {
         _componentIdentity = new ComponentIdentity(GetType());
     }
     catch (IndexOutOfRangeException)
     {
         throw new MissingComponentIdentityException();
     }
     
 }
        public async Task<bool> HandleRestart(Exception ex, int retryCount, ILogger logger, IComponentIdentity component)
        {
            try
            {
                bool doDelay = retryCount % 5 == 0;

                if (doDelay)
                {
                    logger?.Warning("Error occurred in component {0}. Restarting in 30 seconds.", ex, component.FullyQualifiedName);
                    await Task.Delay(TimeSpan.FromSeconds(30));
                }
                else
                {
                    logger?.Warning("Error occurred in component {0}. Restarting immediately.", ex, component.FullyQualifiedName);
                }
            }
            catch (Exception)
            {
                // swallow any issues
            }
            return true;
        }
        private static async Task<bool> RestartHandler(Exception ex, int retryCount, IAsynchronousLogger logger, IComponentIdentity component)
        {
            try
            {
                bool doDelay = retryCount % 5 == 0;

                if (doDelay)
                {
                    await
                        logger.WarningAsync(
                            $"Error occurred in component {component.FullyQualifiedName}. Restarting in 30 seconds.", ex);
                    await Task.Delay(TimeSpan.FromSeconds(30));
                }
                else
                {
                    await logger.WarningAsync($"Error occurred in component {component.FullyQualifiedName}. Restarting immediately.", ex);
                }
            }
            catch (Exception)
            {
                // swallow any issues
            }
            return true;
        }
 public string ServiceBusConnectionString(IComponentIdentity componentIdentity)
 {
     return _configuration[_nameProvider.ServiceBusConnectionString(componentIdentity)];
 }
 public string DefaultBlobContainerName(IComponentIdentity componentIdentity)
 {
     return _configuration[_nameProvider.DefaultBlobContainerName(componentIdentity)];
 }
 public string DefaultLeaseBlockName(IComponentIdentity componentIdentity)
 {
     return _configuration[_nameProvider.DefaultLeaseBlockName(componentIdentity)];
 }
 public Task<string> DefaultSubscriptionNameAsync(IComponentIdentity componentIdentity)
 {
     return _configuration.GetAsync(_nameProvider.DefaultSubscriptionName(componentIdentity));
 }
 /// <summary>
 /// Default brokered message queue name setting.
 /// Format: {componentIdentity}.default-brokered-message-queue-name
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string DefaultBrokeredMessageQueueName(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.default-brokered-message-queue-name";
 }
 public Task<string> SqlContextTypeAsync(IComponentIdentity componentIdentity)
 {
     return _configuration.GetAsync(_nameProvider.SqlContextType(componentIdentity));
 }
 public Task<string> DefaultBlobContainerNameAsync(IComponentIdentity componentIdentity)
 {
     return _configuration.GetAsync(_nameProvider.DefaultBlobContainerName(componentIdentity));
 }
 /// <summary>
 /// Default blob container name setting.
 /// Format: {componentIdentity}.default-blob-container-name
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string DefaultBlobContainerName(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.default-blob-container-name";
 }
 /// <summary>
 /// Default topic name setting.
 /// Format: {componentIdentity}.default-topic-name
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string DefaultTopicName(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.default-topic-name";
 }
 /// <summary>
 /// Service bus connection string setting.
 /// Format: {componentIdentity}.service-bus-connection-string
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string ServiceBusConnectionString(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.service-bus-connection-string";
 }
 /// <summary>
 /// Default queue name setting.
 /// Format: {componentIdentity}.default-queue-name
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string DefaultQueueName(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.default-queue-name";
 }
 /// <summary>
 /// Storage account connection string setting.
 /// Format: {componentIdentity}.storage-account-connection-string
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string StorageAccountConnectionString(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.storage-account-connection-string";
 }
 /// <summary>
 /// Database context setting.
 /// Format: {componentIdentity}.db-context-type
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string SqlContextType(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.db-context-type";
 }
 /// <summary>
 /// SQL connection string setting.
 /// Format: {componentIdentity}.sql-connection-string
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string SqlConnectionString(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.sql-connection-string";
 }
 public string DefaultSubscriptionName(IComponentIdentity componentIdentity)
 {
     return _configuration[_nameProvider.DefaultSubscriptionName(componentIdentity)];
 }
 /// <summary>
 /// Application setting name .
 /// Format: {componentIdentity}.setting.{setting}
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <param name="setting">Name of the setting</param>
 /// <returns>Setting name</returns>
 public string SettingName(IComponentIdentity componentIdentity, string setting)
 {
     return $"{componentIdentity.FullyQualifiedName}.setting.{setting}";
 }
 public string DefaultBrokeredMessageQueueName(IComponentIdentity componentIdentity)
 {
     return _configuration[_nameProvider.DefaultBrokeredMessageQueueName(componentIdentity)];
 }
 /// <summary>
 /// Default subscription name setting.
 /// Format: {componentIdentity}.default-subscription-name
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string DefaultSubscriptionName(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.default-subscription-name";
 }
 public Task<string> StorageAccountConnectionStringAsync(IComponentIdentity componentIdentity)
 {
     return _configuration.GetAsync(_nameProvider.StorageAccountConnectionString(componentIdentity));
 }
 public string SqlContextType(IComponentIdentity componentIdentity)
 {
     return _configuration[_nameProvider.SqlContextType(componentIdentity)];
 }
 public Task<string> ServiceBusConnectionStringAsync(IComponentIdentity componentIdentity)
 {
     return _configuration.GetAsync(_nameProvider.ServiceBusConnectionString(componentIdentity));
 }
 public string StorageAccountConnectionString(IComponentIdentity componentIdentity)
 {
     return _configuration[_nameProvider.StorageAccountConnectionString(componentIdentity)];
 }
 public Task<string> DefaultBrokeredMessageQueueNameAsync(IComponentIdentity componentIdentity)
 {
     return _configuration.GetAsync(_nameProvider.DefaultBrokeredMessageQueueName(componentIdentity));
 }
 /// <summary>
 /// Default lease block name.
 /// Format: {componentIdentity}.default-lease-block-name
 /// </summary>
 /// <param name="componentIdentity">The component identity</param>
 /// <returns>Setting name</returns>
 public string DefaultLeaseBlockName(IComponentIdentity componentIdentity)
 {
     return $"{componentIdentity.FullyQualifiedName}.default-lease-block-name";
 }