public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            ParameterInfo parameter            = context.Parameter;
            var           blobTriggerAttribute = TypeUtility.GetResolvedAttribute <BlobTriggerAttribute>(context.Parameter);

            if (blobTriggerAttribute == null)
            {
                return(null);
            }

            string          resolvedCombinedPath = Resolve(blobTriggerAttribute.BlobPath);
            IBlobPathSource path = BlobPathSource.Create(resolvedCombinedPath);

            IStorageAccount hostAccount = await _accountProvider.GetStorageAccountAsync(context.CancellationToken);

            IStorageAccount dataAccount = await _accountProvider.GetStorageAccountAsync(blobTriggerAttribute, context.CancellationToken, _nameResolver);

            // premium does not support blob logs, so disallow for blob triggers
            dataAccount.AssertTypeOneOf(StorageAccountType.GeneralPurpose, StorageAccountType.BlobOnly);

            ITriggerBinding binding = new BlobTriggerBinding(parameter, hostAccount, dataAccount, path,
                                                             _hostIdProvider, _queueConfiguration, _blobsConfiguration, _exceptionHandler, _blobWrittenWatcherSetter,
                                                             _messageEnqueuedWatcherSetter, _sharedContextProvider, _singletonManager, _loggerFactory);

            return(binding);
        }
        public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            ParameterInfo        parameter            = context.Parameter;
            BlobTriggerAttribute blobTriggerAttribute = parameter.GetCustomAttribute <BlobTriggerAttribute>(inherit: false);

            if (blobTriggerAttribute == null)
            {
                return(null);
            }

            string          resolvedCombinedPath = Resolve(blobTriggerAttribute.BlobPath);
            IBlobPathSource path = BlobPathSource.Create(resolvedCombinedPath);

            IArgumentBinding <IStorageBlob> argumentBinding = _provider.TryCreate(parameter, access: null);

            if (argumentBinding == null)
            {
                throw new InvalidOperationException("Can't bind BlobTrigger to type '" + parameter.ParameterType + "'.");
            }

            IStorageAccount hostAccount = await _accountProvider.GetStorageAccountAsync(context.CancellationToken);

            IStorageAccount dataAccount = await _accountProvider.GetStorageAccountAsync(context.Parameter, context.CancellationToken, _nameResolver);

            // premium does not support blob logs, so disallow for blob triggers
            dataAccount.AssertTypeOneOf(StorageAccountType.GeneralPurpose, StorageAccountType.BlobOnly);

            ITriggerBinding binding = new BlobTriggerBinding(parameter, argumentBinding, hostAccount, dataAccount, path,
                                                             _hostIdProvider, _queueConfiguration, _exceptionHandler, _blobWrittenWatcherSetter,
                                                             _messageEnqueuedWatcherSetter, _sharedContextProvider, _singletonManager, _trace);

            return(binding);
        }
        public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            ParameterInfo        parameter            = context.Parameter;
            BlobTriggerAttribute blobTriggerAttribute = parameter.GetCustomAttribute <BlobTriggerAttribute>(inherit: false);

            if (blobTriggerAttribute == null)
            {
                return(null);
            }

            string          resolvedCombinedPath = Resolve(blobTriggerAttribute.BlobPath);
            IBlobPathSource path = BlobPathSource.Create(resolvedCombinedPath);

            IArgumentBinding <IStorageBlob> argumentBinding = _provider.TryCreate(parameter, access: null);

            if (argumentBinding == null)
            {
                throw new InvalidOperationException("Can't bind BlobTrigger to type '" + parameter.ParameterType + "'.");
            }

            IStorageAccount hostAccount = await _accountProvider.GetStorageAccountAsync(context.CancellationToken);

            IStorageAccount dataAccount = await _accountProvider.GetStorageAccountAsync(context.Parameter, context.CancellationToken, _nameResolver);

            ITriggerBinding binding = new BlobTriggerBinding(parameter, argumentBinding, hostAccount, dataAccount, path,
                                                             _hostIdProvider, _queueConfiguration, _backgroundExceptionDispatcher, _blobWrittenWatcherSetter,
                                                             _messageEnqueuedWatcherSetter, _sharedContextProvider, _trace);

            return(binding);
        }
Esempio n. 4
0
            private ParameterDescriptor ToParameterDescriptorForCollector(QueueAttribute attr, ParameterInfo parameter, INameResolver nameResolver, FileAccess access)
            {
                // Avoid using the sync over async pattern (Async().GetAwaiter().GetResult()) whenever possible
                IStorageAccount account = _accountProvider.GetStorageAccountAsync(attr, CancellationToken.None, nameResolver).GetAwaiter().GetResult();

                string accountName = account.Credentials.AccountName;

                return(new QueueParameterDescriptor
                {
                    Name = parameter.Name,
                    AccountName = accountName,
                    QueueName = NormalizeQueueName(attr, nameResolver),
                    Access = access
                });
            }
Esempio n. 5
0
            private ParameterDescriptor ToParameterDescriptorForCollector(QueueAttribute attr, ParameterInfo parameter, INameResolver nameResolver, FileAccess access)
            {
                Task <IStorageAccount> t = Task.Run(() =>
                                                    _accountProvider.GetStorageAccountAsync(attr, CancellationToken.None, nameResolver));
                IStorageAccount account = t.GetAwaiter().GetResult();

                string accountName = account.Credentials.AccountName;

                return(new QueueParameterDescriptor
                {
                    Name = parameter.Name,
                    AccountName = accountName,
                    QueueName = NormalizeQueueName(attr, nameResolver),
                    Access = access
                });
            }
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            ParameterInfo  parameter      = context.Parameter;
            QueueAttribute queueAttribute = parameter.GetCustomAttribute <QueueAttribute>(inherit: false);

            if (queueAttribute == null)
            {
                return(null);
            }

            string             queueName = Resolve(queueAttribute.QueueName);
            IBindableQueuePath path      = BindableQueuePath.Create(queueName);

            path.ValidateContractCompatibility(context.BindingDataContract);

            IArgumentBinding <IStorageQueue> argumentBinding = _innerProvider.TryCreate(parameter);

            if (argumentBinding == null)
            {
                throw new InvalidOperationException("Can't bind Queue to type '" + parameter.ParameterType + "'.");
            }

            IStorageAccount account = await _accountProvider.GetStorageAccountAsync(context.Parameter, context.CancellationToken);

            StorageClientFactoryContext clientFactoryContext = new StorageClientFactoryContext
            {
                Parameter = parameter
            };
            IStorageQueueClient client  = account.CreateQueueClient(clientFactoryContext);
            IBinding            binding = new QueueBinding(parameter.Name, argumentBinding, client, path);

            return(binding);
        }
 public FakeQueueProcessorFactory(IStorageAccountProvider accountProvider)
 {
     CancellationToken token = new CancellationToken();
     Task<IStorageAccount> task = accountProvider.GetStorageAccountAsync(token);
     task.Wait();
     _storageAccount = task.Result;
 }
Esempio n. 8
0
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            ParameterInfo parameter = context.Parameter;
            BlobAttribute blob      = parameter.GetCustomAttribute <BlobAttribute>(inherit: false);

            if (blob == null)
            {
                return(null);
            }

            string            resolvedCombinedPath = Resolve(blob.BlobPath);
            IBindableBlobPath path = BindableBlobPath.Create(resolvedCombinedPath);

            path.ValidateContractCompatibility(context.BindingDataContract);

            IBlobArgumentBinding argumentBinding = _provider.TryCreate(parameter, blob.Access);

            if (argumentBinding == null)
            {
                throw new InvalidOperationException("Can't bind Blob to type '" + parameter.ParameterType + "'.");
            }

            IStorageAccount account = await _accountProvider.GetStorageAccountAsync(context.CancellationToken);

            IStorageBlobClient client  = account.CreateBlobClient();
            IBinding           binding = new BlobBinding(parameter.Name, argumentBinding, client, path);

            return(binding);
        }
        public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            ParameterInfo         parameter    = context.Parameter;
            QueueTriggerAttribute queueTrigger = parameter.GetCustomAttribute <QueueTriggerAttribute>(inherit: false);

            if (queueTrigger == null)
            {
                return(null);
            }

            string queueName = Resolve(queueTrigger.QueueName);

            queueName = NormalizeAndValidate(queueName);

            ITriggerDataArgumentBinding <IStorageQueueMessage> argumentBinding = _innerProvider.TryCreate(parameter);

            if (argumentBinding == null)
            {
                throw new InvalidOperationException(
                          "Can't bind QueueTrigger to type '" + parameter.ParameterType + "'.");
            }

            IStorageAccount account = await _accountProvider.GetStorageAccountAsync(context.CancellationToken);

            IStorageQueueClient client = account.CreateQueueClient();
            IStorageQueue       queue  = client.GetQueueReference(queueName);

            ITriggerBinding binding = new QueueTriggerBinding(parameter.Name, queue, argumentBinding,
                                                              _queueConfiguration, _backgroundExceptionDispatcher, _messageEnqueuedWatcherSetter,
                                                              _sharedContextProvider, _log);

            return(binding);
        }
        private async Task EnsureLoggersAsync(CancellationToken cancellationToken)
        {
            if (_loggersSet)
            {
                return;
            }

            IStorageAccount dashboardAccount = await _storageAccountProvider.GetDashboardAccountAsync(cancellationToken);

            IStorageAccount storageAccount = await _storageAccountProvider.GetStorageAccountAsync(cancellationToken);

            IFunctionInstanceLogger traceWriterFunctionLogger = new TraceWriterFunctionInstanceLogger(_trace);

            if (dashboardAccount != null)
            {
                // Create logging against a live Azure account.
                IStorageBlobClient dashboardBlobClient = dashboardAccount.CreateBlobClient();
                IPersistentQueueWriter <PersistentQueueMessage> queueWriter = new PersistentQueueWriter <PersistentQueueMessage>(dashboardBlobClient);
                PersistentQueueLogger queueLogger = new PersistentQueueLogger(queueWriter);
                _hostInstanceLogger     = queueLogger;
                _functionInstanceLogger = new CompositeFunctionInstanceLogger(queueLogger, traceWriterFunctionLogger);
                _functionOutputLogger   = new BlobFunctionOutputLogger(dashboardBlobClient);
            }
            else
            {
                // No auxillary logging. Logging interfaces are nops or in-memory.
                _hostInstanceLogger     = new NullHostInstanceLogger();
                _functionInstanceLogger = traceWriterFunctionLogger;
                _functionOutputLogger   = new ConsoleFunctionOutputLogger();
            }

            _loggersSet = true;
        }
Esempio n. 11
0
        public async Task <string> GetHostIdAsync(CancellationToken cancellationToken)
        {
            IStorageAccount account;

            try
            {
                account = await _storageAccountProvider.GetStorageAccountAsync(cancellationToken);
            }
            catch (InvalidOperationException exception)
            {
                throw new InvalidOperationException(
                          "A host ID is required. Either set JobHostConfiguration.HostId or provide a valid storage " +
                          "connection string.", exception);
            }

            IFunctionIndex index = await _getFunctionIndexProvider.Invoke().GetAsync(cancellationToken);

            IEnumerable <MethodInfo> indexedMethods = index.ReadAllMethods();

            string sharedHostName           = GetSharedHostName(indexedMethods, account);
            IStorageBlobDirectory directory = account.CreateBlobClient().GetContainerReference(
                HostContainerNames.Hosts).GetDirectoryReference(HostDirectoryNames.Ids);

            return(await GetOrCreateHostIdAsync(sharedHostName, directory, cancellationToken));
        }
Esempio n. 12
0
            public FakeQueueProcessorFactory(IStorageAccountProvider accountProvider)
            {
                CancellationToken      token = new CancellationToken();
                Task <IStorageAccount> task  = accountProvider.GetStorageAccountAsync(token);

                _storageAccount = task.Result;
            }
        private async Task <IStorageBlobClient> GetClientAsync(
            BlobAttribute blobAttribute,
            CancellationToken cancellationToken)
        {
            IStorageAccount account = await _accountProvider.GetStorageAccountAsync(blobAttribute, cancellationToken, _nameResolver);

            IStorageBlobClient client = account.CreateBlobClient();

            return(client);
        }
Esempio n. 14
0
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            ParameterInfo  parameter      = context.Parameter;
            TableAttribute tableAttribute = parameter.GetCustomAttribute <TableAttribute>(inherit: false);

            if (tableAttribute == null)
            {
                return(null);
            }

            string          tableName = Resolve(tableAttribute.TableName);
            IStorageAccount account   = await _accountProvider.GetStorageAccountAsync(context.Parameter, context.CancellationToken, _nameResolver);

            StorageClientFactoryContext clientFactoryContext = new StorageClientFactoryContext
            {
                Parameter = context.Parameter
            };
            IStorageTableClient client = account.CreateTableClient(clientFactoryContext);

            bool     bindsToEntireTable = tableAttribute.RowKey == null;
            IBinding binding;

            if (bindsToEntireTable)
            {
                IBindableTablePath path = BindableTablePath.Create(tableName);
                path.ValidateContractCompatibility(context.BindingDataContract);

                IStorageTableArgumentBinding argumentBinding = _tableBindingProvider.TryCreate(parameter);

                if (argumentBinding == null)
                {
                    throw new InvalidOperationException("Can't bind Table to type '" + parameter.ParameterType + "'.");
                }

                binding = new TableBinding(parameter.Name, argumentBinding, client, path);
            }
            else
            {
                string partitionKey           = Resolve(tableAttribute.PartitionKey);
                string rowKey                 = Resolve(tableAttribute.RowKey);
                IBindableTableEntityPath path = BindableTableEntityPath.Create(tableName, partitionKey, rowKey);
                path.ValidateContractCompatibility(context.BindingDataContract);

                IArgumentBinding <TableEntityContext> argumentBinding = _entityBindingProvider.TryCreate(parameter);

                if (argumentBinding == null)
                {
                    throw new InvalidOperationException("Can't bind Table entity to type '" + parameter.ParameterType + "'.");
                }

                binding = new TableEntityBinding(parameter.Name, argumentBinding, client, path);
            }

            return(binding);
        }
Esempio n. 15
0
            protected override IStorageBlobContainer GetContainer(string accountName)
            {
                // Get the container via a full connection string
                Task <IStorageAccount> task           = _accountProvider.GetStorageAccountAsync(accountName, CancellationToken.None);
                IStorageAccount        storageAccount = task.Result;

                // singleton requires block blobs, cannot be premium
                storageAccount.AssertTypeOneOf(StorageAccountType.GeneralPurpose, StorageAccountType.BlobOnly);
                IStorageBlobClient blobClient = storageAccount.CreateBlobClient();
                var container = blobClient.GetContainerReference(HostContainerNames.Hosts);

                return(container);
            }
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            ParameterInfo parameter      = context.Parameter;
            var           tableAttribute = TypeUtility.GetResolvedAttribute <TableAttribute>(context.Parameter);

            if (tableAttribute == null)
            {
                return(null);
            }

            string          tableName = Resolve(tableAttribute.TableName);
            IStorageAccount account   = await _accountProvider.GetStorageAccountAsync(tableAttribute, context.CancellationToken, _nameResolver);

            // requires storage account with table support
            account.AssertTypeOneOf(StorageAccountType.GeneralPurpose);

            StorageClientFactoryContext clientFactoryContext = new StorageClientFactoryContext
            {
                Parameter = context.Parameter
            };
            IStorageTableClient client = account.CreateTableClient(clientFactoryContext);

            bool     bindsToEntireTable = tableAttribute.RowKey == null;
            IBinding binding;

            if (bindsToEntireTable)
            {
                // This should have been caught by the other rule-based binders.
                // We never expect this to get thrown.
                throw new InvalidOperationException("Can't bind Table to type '" + parameter.ParameterType + "'.");
            }
            else
            {
                string partitionKey           = Resolve(tableAttribute.PartitionKey);
                string rowKey                 = Resolve(tableAttribute.RowKey);
                IBindableTableEntityPath path = BindableTableEntityPath.Create(tableName, partitionKey, rowKey);
                path.ValidateContractCompatibility(context.BindingDataContract);

                IArgumentBinding <TableEntityContext> argumentBinding = _entityBindingProvider.TryCreate(parameter);

                if (argumentBinding == null)
                {
                    throw new InvalidOperationException("Can't bind Table entity to type '" + parameter.ParameterType + "'.");
                }

                binding = new TableEntityBinding(parameter.Name, argumentBinding, client, path);
            }

            return(binding);
        }
        // For describing InvokeStrings.
        private async Task <IStorageBlob> ConvertFromInvokeString(DirectInvokeString input, Attribute attr, ValueBindingContext context)
        {
            var attrResolved = (BlobTriggerAttribute)attr;
            var account      = await _accountProvider.GetStorageAccountAsync(attrResolved, CancellationToken.None);

            var client = account.CreateBlobClient();

            var      cancellationToken = context.CancellationToken;
            BlobPath path = BlobPath.ParseAndValidate(input.Value);
            IStorageBlobContainer container = client.GetContainerReference(path.ContainerName);
            var blob = await container.GetBlobReferenceFromServerAsync(path.BlobName, cancellationToken);

            return(blob);
        }
Esempio n. 18
0
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            ParameterInfo parameter = context.Parameter;

            if (parameter.ParameterType != typeof(CloudStorageAccount))
            {
                return(null);
            }

            var accountAttribute = TypeUtility.GetHierarchicalAttributeOrNull <StorageAccountAttribute>(parameter);
            var account          = await _accountProvider.GetStorageAccountAsync(accountAttribute?.Account, context.CancellationToken);

            return(new CloudStorageAccountBinding(parameter.Name, account.SdkObject));
        }
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            ParameterInfo parameter = context.Parameter;

            if (context.Parameter.ParameterType != typeof(CloudStorageAccount))
            {
                return(null);
            }

            IStorageAccount account = await _accountProvider.GetStorageAccountAsync(context.Parameter, context.CancellationToken);

            IBinding binding = new CloudStorageAccountBinding(parameter.Name, account.SdkObject);

            return(binding);
        }
Esempio n. 20
0
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            ParameterInfo parameter     = context.Parameter;
            BlobAttribute blobAttribute = parameter.GetCustomAttribute <BlobAttribute>(inherit: false);

            if (blobAttribute == null)
            {
                return(null);
            }

            string            resolvedPath = Resolve(blobAttribute.BlobPath);
            IBindableBlobPath path         = null;
            IStorageAccount   account      = await _accountProvider.GetStorageAccountAsync(context.Parameter, context.CancellationToken);

            StorageClientFactoryContext clientFactoryContext = new StorageClientFactoryContext
            {
                Parameter = context.Parameter
            };
            IStorageBlobClient client = account.CreateBlobClient(clientFactoryContext);

            // first try to bind to the Container
            IArgumentBinding <IStorageBlobContainer> containerArgumentBinding = _blobContainerArgumentProvider.TryCreate(parameter);

            if (containerArgumentBinding == null)
            {
                // if this isn't a Container binding, try a Blob binding
                IBlobArgumentBinding blobArgumentBinding = _blobArgumentProvider.TryCreate(parameter, blobAttribute.Access);
                if (blobArgumentBinding == null)
                {
                    throw new InvalidOperationException("Can't bind Blob to type '" + parameter.ParameterType + "'.");
                }

                path = BindableBlobPath.Create(resolvedPath);
                path.ValidateContractCompatibility(context.BindingDataContract);

                return(new BlobBinding(parameter.Name, blobArgumentBinding, client, path));
            }

            path = BindableBlobPath.Create(resolvedPath, isContainerBinding: true);
            path.ValidateContractCompatibility(context.BindingDataContract);
            BlobContainerBinding.ValidateContainerBinding(blobAttribute, parameter.ParameterType, path);

            return(new BlobContainerBinding(parameter.Name, containerArgumentBinding, client, path));
        }
        public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            ParameterInfo parameter    = context.Parameter;
            var           queueTrigger = TypeUtility.GetResolvedAttribute <QueueTriggerAttribute>(context.Parameter);

            if (queueTrigger == null)
            {
                return(null);
            }

            string queueName = Resolve(queueTrigger.QueueName);

            queueName = NormalizeAndValidate(queueName);

            ITriggerDataArgumentBinding <IStorageQueueMessage> argumentBinding = InnerProvider.TryCreate(parameter);

            if (argumentBinding == null)
            {
                throw new InvalidOperationException(
                          "Can't bind QueueTrigger to type '" + parameter.ParameterType + "'.");
            }

            IStorageAccount account = await _accountProvider.GetStorageAccountAsync(queueTrigger, context.CancellationToken, _nameResolver);

            // requires storage account with queue support
            account.AssertTypeOneOf(StorageAccountType.GeneralPurpose);

            StorageClientFactoryContext clientFactoryContext = new StorageClientFactoryContext
            {
                Parameter = parameter
            };
            IStorageQueueClient client = account.CreateQueueClient(clientFactoryContext);
            IStorageQueue       queue  = client.GetQueueReference(queueName);

            ITriggerBinding binding = new QueueTriggerBinding(parameter.Name, queue, argumentBinding,
                                                              _queueConfiguration, _exceptionHandler, _messageEnqueuedWatcherSetter,
                                                              _sharedContextProvider, _loggerFactory);

            return(binding);
        }
Esempio n. 22
0
        public static async Task <JobHostContext> CreateAndLogHostStartedAsync(
            IStorageAccountProvider storageAccountProvider,
            IQueueConfiguration queueConfiguration,
            ITypeLocator typeLocator,
            IJobActivator activator,
            INameResolver nameResolver,
            IConsoleProvider consoleProvider,
            JobHostConfiguration config,
            CancellationToken shutdownToken,
            CancellationToken cancellationToken,
            IHostIdProvider hostIdProvider                                 = null,
            FunctionExecutor functionExecutor                              = null,
            IFunctionIndexProvider functionIndexProvider                   = null,
            IBindingProvider bindingProvider                               = null,
            IHostInstanceLoggerProvider hostInstanceLogerProvider          = null,
            IFunctionInstanceLoggerProvider functionInstanceLoggerProvider = null,
            IFunctionOutputLoggerProvider functionOutputLoggerProvider     = null,
            IBackgroundExceptionDispatcher backgroundExceptionDispatcher   = null,
            SingletonManager singletonManager                              = null)
        {
            if (hostIdProvider == null)
            {
                hostIdProvider = new DynamicHostIdProvider(storageAccountProvider, () => functionIndexProvider);
            }

            IExtensionTypeLocator extensionTypeLocator = new ExtensionTypeLocator(typeLocator);

            if (backgroundExceptionDispatcher == null)
            {
                backgroundExceptionDispatcher = BackgroundExceptionDispatcher.Instance;
            }
            ContextAccessor <IMessageEnqueuedWatcher> messageEnqueuedWatcherAccessor = new ContextAccessor <IMessageEnqueuedWatcher>();
            ContextAccessor <IBlobWrittenWatcher>     blobWrittenWatcherAccessor     = new ContextAccessor <IBlobWrittenWatcher>();
            ISharedContextProvider sharedContextProvider = new SharedContextProvider();

            // Create the a wrapper TraceWriter that delegates to both the user
            // TraceWriter specified on Config (if present), as well as to Console
            TraceWriter trace = new ConsoleTraceWriter(config.Tracing, consoleProvider.Out);

            // Register system services with the service container
            config.AddService <INameResolver>(nameResolver);

            ExtensionConfigContext context = new ExtensionConfigContext
            {
                Config = config,
                Trace  = trace
            };

            InvokeExtensionConfigProviders(context);

            IExtensionRegistry      extensions             = config.GetExtensions();
            ITriggerBindingProvider triggerBindingProvider = DefaultTriggerBindingProvider.Create(nameResolver,
                                                                                                  storageAccountProvider, extensionTypeLocator, hostIdProvider, queueConfiguration, backgroundExceptionDispatcher,
                                                                                                  messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, sharedContextProvider, extensions, trace);

            if (bindingProvider == null)
            {
                bindingProvider = DefaultBindingProvider.Create(nameResolver, storageAccountProvider, extensionTypeLocator, messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, extensions);
            }

            DefaultLoggerProvider loggerProvider = new DefaultLoggerProvider(storageAccountProvider, trace);

            if (singletonManager == null)
            {
                IStorageAccount storageAccount = await storageAccountProvider.GetStorageAccountAsync(cancellationToken);

                singletonManager = new SingletonManager(storageAccount.CreateBlobClient(), backgroundExceptionDispatcher, config.Singleton, trace);
            }

            using (CancellationTokenSource combinedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, shutdownToken))
            {
                CancellationToken combinedCancellationToken = combinedCancellationSource.Token;

                await WriteSiteExtensionManifestAsync(combinedCancellationToken);

                IStorageAccount dashboardAccount = await storageAccountProvider.GetDashboardAccountAsync(combinedCancellationToken);

                IHostInstanceLogger hostInstanceLogger = null;
                if (hostInstanceLogerProvider != null)
                {
                    hostInstanceLogger = await hostInstanceLogerProvider.GetAsync(combinedCancellationToken);
                }
                else
                {
                    hostInstanceLogger = await((IHostInstanceLoggerProvider)loggerProvider).GetAsync(combinedCancellationToken);
                }

                IFunctionInstanceLogger functionInstanceLogger = null;
                if (functionInstanceLoggerProvider != null)
                {
                    functionInstanceLogger = await functionInstanceLoggerProvider.GetAsync(combinedCancellationToken);
                }
                else
                {
                    functionInstanceLogger = (IFunctionInstanceLogger)(await((IFunctionInstanceLoggerProvider)loggerProvider).GetAsync(combinedCancellationToken));
                }

                IFunctionOutputLogger functionOutputLogger = null;
                if (functionOutputLoggerProvider != null)
                {
                    functionOutputLogger = await functionOutputLoggerProvider.GetAsync(combinedCancellationToken);
                }
                else
                {
                    functionOutputLogger = (IFunctionOutputLogger)(await((IFunctionOutputLoggerProvider)loggerProvider).GetAsync(combinedCancellationToken));
                }

                if (functionExecutor == null)
                {
                    functionExecutor = new FunctionExecutor(functionInstanceLogger, functionOutputLogger, backgroundExceptionDispatcher, trace);
                }

                if (functionIndexProvider == null)
                {
                    functionIndexProvider = new FunctionIndexProvider(typeLocator, triggerBindingProvider, bindingProvider, activator, functionExecutor, extensions, singletonManager);
                }

                IFunctionIndex functions = await functionIndexProvider.GetAsync(combinedCancellationToken);

                IListenerFactory functionsListenerFactory = new HostListenerFactory(functions.ReadAll(), singletonManager);

                IFunctionExecutor hostCallExecutor;
                IListener         listener;
                HostOutputMessage hostOutputMessage;

                if (dashboardAccount != null)
                {
                    string hostId = await hostIdProvider.GetHostIdAsync(cancellationToken);

                    string sharedQueueName = HostQueueNames.GetHostQueueName(hostId);
                    IStorageQueueClient dashboardQueueClient       = dashboardAccount.CreateQueueClient();
                    IStorageQueue       sharedQueue                = dashboardQueueClient.GetQueueReference(sharedQueueName);
                    IListenerFactory    sharedQueueListenerFactory = new HostMessageListenerFactory(sharedQueue,
                                                                                                    queueConfiguration, backgroundExceptionDispatcher, trace, functions,
                                                                                                    functionInstanceLogger, functionExecutor);

                    Guid             hostInstanceId               = Guid.NewGuid();
                    string           instanceQueueName            = HostQueueNames.GetHostQueueName(hostInstanceId.ToString("N"));
                    IStorageQueue    instanceQueue                = dashboardQueueClient.GetQueueReference(instanceQueueName);
                    IListenerFactory instanceQueueListenerFactory = new HostMessageListenerFactory(instanceQueue,
                                                                                                   queueConfiguration, backgroundExceptionDispatcher, trace, functions,
                                                                                                   functionInstanceLogger, functionExecutor);

                    HeartbeatDescriptor heartbeatDescriptor = new HeartbeatDescriptor
                    {
                        SharedContainerName = HostContainerNames.Hosts,
                        SharedDirectoryName = HostDirectoryNames.Heartbeats + "/" + hostId,
                        InstanceBlobName    = hostInstanceId.ToString("N"),
                        ExpirationInSeconds = (int)HeartbeatIntervals.ExpirationInterval.TotalSeconds
                    };
                    IRecurrentCommand heartbeatCommand = new UpdateHostHeartbeatCommand(new HeartbeatCommand(
                                                                                            dashboardAccount,
                                                                                            heartbeatDescriptor.SharedContainerName,
                                                                                            heartbeatDescriptor.SharedDirectoryName + "/" + heartbeatDescriptor.InstanceBlobName));

                    IEnumerable <MethodInfo> indexedMethods = functions.ReadAllMethods();
                    Assembly hostAssembly = GetHostAssembly(indexedMethods);
                    string   displayName  = hostAssembly != null?hostAssembly.GetName().Name : "Unknown";

                    hostOutputMessage = new DataOnlyHostOutputMessage
                    {
                        HostInstanceId      = hostInstanceId,
                        HostDisplayName     = displayName,
                        SharedQueueName     = sharedQueueName,
                        InstanceQueueName   = instanceQueueName,
                        Heartbeat           = heartbeatDescriptor,
                        WebJobRunIdentifier = WebJobRunIdentifier.Current
                    };

                    hostCallExecutor = CreateHostCallExecutor(instanceQueueListenerFactory, heartbeatCommand,
                                                              backgroundExceptionDispatcher, shutdownToken, functionExecutor);
                    IListenerFactory hostListenerFactory = new CompositeListenerFactory(functionsListenerFactory,
                                                                                        sharedQueueListenerFactory, instanceQueueListenerFactory);
                    listener = CreateHostListener(hostListenerFactory, heartbeatCommand, backgroundExceptionDispatcher, shutdownToken);

                    // Publish this to Azure logging account so that a web dashboard can see it.
                    await LogHostStartedAsync(functions, hostOutputMessage, hostInstanceLogger, combinedCancellationToken);
                }
                else
                {
                    hostCallExecutor = new ShutdownFunctionExecutor(shutdownToken, functionExecutor);

                    IListener factoryListener  = new ListenerFactoryListener(functionsListenerFactory);
                    IListener shutdownListener = new ShutdownListener(shutdownToken, factoryListener);
                    listener = shutdownListener;

                    hostOutputMessage = new DataOnlyHostOutputMessage();
                }

                functionExecutor.HostOutputMessage = hostOutputMessage;

                IEnumerable <FunctionDescriptor> descriptors = functions.ReadAllDescriptors();
                int descriptorsCount = descriptors.Count();

                if (descriptorsCount == 0)
                {
                    trace.Warning("No functions found. Try making job classes and methods public.", TraceSource.Indexing);
                }
                else
                {
                    StringBuilder functionsTrace = new StringBuilder();
                    functionsTrace.AppendLine("Found the following functions:");

                    foreach (FunctionDescriptor descriptor in descriptors)
                    {
                        functionsTrace.AppendLine(descriptor.FullName);
                    }

                    trace.Info(functionsTrace.ToString(), TraceSource.Indexing);
                }

                return(new JobHostContext(functions, hostCallExecutor, listener, trace));
            }
        }
        public static async Task<JobHostContext> CreateAndLogHostStartedAsync(
            IStorageAccountProvider storageAccountProvider,
            IQueueConfiguration queueConfiguration,
            ITypeLocator typeLocator,
            IJobActivator activator,
            INameResolver nameResolver,
            IConsoleProvider consoleProvider,
            JobHostConfiguration config,
            CancellationToken shutdownToken,
            CancellationToken cancellationToken,
            IHostIdProvider hostIdProvider = null,
            FunctionExecutor functionExecutor = null,
            IFunctionIndexProvider functionIndexProvider = null,
            IBindingProvider bindingProvider = null,
            IHostInstanceLoggerProvider hostInstanceLogerProvider = null,
            IFunctionInstanceLoggerProvider functionInstanceLoggerProvider = null,
            IFunctionOutputLoggerProvider functionOutputLoggerProvider = null,
            IBackgroundExceptionDispatcher backgroundExceptionDispatcher = null,
            SingletonManager singletonManager = null)
        {
            if (hostIdProvider == null)
            {
                hostIdProvider = new DynamicHostIdProvider(storageAccountProvider, () => functionIndexProvider);
            }

            IExtensionTypeLocator extensionTypeLocator = new ExtensionTypeLocator(typeLocator);
            if (backgroundExceptionDispatcher == null)
            {
                backgroundExceptionDispatcher = BackgroundExceptionDispatcher.Instance;
            }
            ContextAccessor<IMessageEnqueuedWatcher> messageEnqueuedWatcherAccessor = new ContextAccessor<IMessageEnqueuedWatcher>();
            ContextAccessor<IBlobWrittenWatcher> blobWrittenWatcherAccessor = new ContextAccessor<IBlobWrittenWatcher>();
            ISharedContextProvider sharedContextProvider = new SharedContextProvider();

            // Create the a wrapper TraceWriter that delegates to both the user 
            // TraceWriter specified on Config (if present), as well as to Console
            TraceWriter trace = new ConsoleTraceWriter(config.Tracing, consoleProvider.Out);

            // Register system services with the service container
            config.AddService<INameResolver>(nameResolver);

            ExtensionConfigContext context = new ExtensionConfigContext
            {
                Config = config,
                Trace = trace
            };
            InvokeExtensionConfigProviders(context);

            IExtensionRegistry extensions = config.GetExtensions();
            ITriggerBindingProvider triggerBindingProvider = DefaultTriggerBindingProvider.Create(nameResolver,
                storageAccountProvider, extensionTypeLocator, hostIdProvider, queueConfiguration, backgroundExceptionDispatcher,
                messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, sharedContextProvider, extensions, trace);

            if (bindingProvider == null)
            {
                bindingProvider = DefaultBindingProvider.Create(nameResolver, storageAccountProvider, extensionTypeLocator, messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, extensions);
            }

            DefaultLoggerProvider loggerProvider = new DefaultLoggerProvider(storageAccountProvider, trace);

            if (singletonManager == null)
            {
                IStorageAccount storageAccount = await storageAccountProvider.GetStorageAccountAsync(cancellationToken);
                singletonManager = new SingletonManager(storageAccount.CreateBlobClient(), backgroundExceptionDispatcher, config.Singleton, trace);
            }
            
            using (CancellationTokenSource combinedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, shutdownToken))
            {
                CancellationToken combinedCancellationToken = combinedCancellationSource.Token;

                await WriteSiteExtensionManifestAsync(combinedCancellationToken);

                IStorageAccount dashboardAccount = await storageAccountProvider.GetDashboardAccountAsync(combinedCancellationToken);

                IHostInstanceLogger hostInstanceLogger = null;
                if (hostInstanceLogerProvider != null)
                {
                    hostInstanceLogger = await hostInstanceLogerProvider.GetAsync(combinedCancellationToken);
                }
                else
                {
                    hostInstanceLogger = await((IHostInstanceLoggerProvider)loggerProvider).GetAsync(combinedCancellationToken);
                }

                IFunctionInstanceLogger functionInstanceLogger = null;
                if (functionInstanceLoggerProvider != null)
                {
                    functionInstanceLogger = await functionInstanceLoggerProvider.GetAsync(combinedCancellationToken);
                }
                else
                {
                    functionInstanceLogger = (IFunctionInstanceLogger)(await((IFunctionInstanceLoggerProvider)loggerProvider).GetAsync(combinedCancellationToken));
                }

                IFunctionOutputLogger functionOutputLogger = null;
                if (functionOutputLoggerProvider != null)
                {
                    functionOutputLogger = await functionOutputLoggerProvider.GetAsync(combinedCancellationToken);
                }
                else
                {
                    functionOutputLogger = (IFunctionOutputLogger)(await((IFunctionOutputLoggerProvider)loggerProvider).GetAsync(combinedCancellationToken));
                }

                if (functionExecutor == null)
                {
                    functionExecutor = new FunctionExecutor(functionInstanceLogger, functionOutputLogger, backgroundExceptionDispatcher, trace);
                }

                if (functionIndexProvider == null)
                {
                    functionIndexProvider = new FunctionIndexProvider(typeLocator, triggerBindingProvider, bindingProvider, activator, functionExecutor, extensions, singletonManager);
                }

                IFunctionIndex functions = await functionIndexProvider.GetAsync(combinedCancellationToken);
                IListenerFactory functionsListenerFactory = new HostListenerFactory(functions.ReadAll(), singletonManager);

                IFunctionExecutor hostCallExecutor;
                IListener listener;
                HostOutputMessage hostOutputMessage;

                if (dashboardAccount != null)
                {
                    string hostId = await hostIdProvider.GetHostIdAsync(cancellationToken);

                    string sharedQueueName = HostQueueNames.GetHostQueueName(hostId);
                    IStorageQueueClient dashboardQueueClient = dashboardAccount.CreateQueueClient();
                    IStorageQueue sharedQueue = dashboardQueueClient.GetQueueReference(sharedQueueName);
                    IListenerFactory sharedQueueListenerFactory = new HostMessageListenerFactory(sharedQueue,
                        queueConfiguration, backgroundExceptionDispatcher, trace, functions,
                        functionInstanceLogger, functionExecutor);

                    Guid hostInstanceId = Guid.NewGuid();
                    string instanceQueueName = HostQueueNames.GetHostQueueName(hostInstanceId.ToString("N"));
                    IStorageQueue instanceQueue = dashboardQueueClient.GetQueueReference(instanceQueueName);
                    IListenerFactory instanceQueueListenerFactory = new HostMessageListenerFactory(instanceQueue,
                        queueConfiguration, backgroundExceptionDispatcher, trace, functions,
                        functionInstanceLogger, functionExecutor);

                    HeartbeatDescriptor heartbeatDescriptor = new HeartbeatDescriptor
                    {
                        SharedContainerName = HostContainerNames.Hosts,
                        SharedDirectoryName = HostDirectoryNames.Heartbeats + "/" + hostId,
                        InstanceBlobName = hostInstanceId.ToString("N"),
                        ExpirationInSeconds = (int)HeartbeatIntervals.ExpirationInterval.TotalSeconds
                    };
                    IRecurrentCommand heartbeatCommand = new UpdateHostHeartbeatCommand(new HeartbeatCommand(
                        dashboardAccount,
                        heartbeatDescriptor.SharedContainerName,
                        heartbeatDescriptor.SharedDirectoryName + "/" + heartbeatDescriptor.InstanceBlobName));

                    IEnumerable<MethodInfo> indexedMethods = functions.ReadAllMethods();
                    Assembly hostAssembly = GetHostAssembly(indexedMethods);
                    string displayName = hostAssembly != null ? hostAssembly.GetName().Name : "Unknown";

                    hostOutputMessage = new DataOnlyHostOutputMessage
                    {
                        HostInstanceId = hostInstanceId,
                        HostDisplayName = displayName,
                        SharedQueueName = sharedQueueName,
                        InstanceQueueName = instanceQueueName,
                        Heartbeat = heartbeatDescriptor,
                        WebJobRunIdentifier = WebJobRunIdentifier.Current
                    };

                    hostCallExecutor = CreateHostCallExecutor(instanceQueueListenerFactory, heartbeatCommand,
                        backgroundExceptionDispatcher, shutdownToken, functionExecutor);
                    IListenerFactory hostListenerFactory = new CompositeListenerFactory(functionsListenerFactory,
                        sharedQueueListenerFactory, instanceQueueListenerFactory);
                    listener = CreateHostListener(hostListenerFactory, heartbeatCommand, backgroundExceptionDispatcher, shutdownToken);

                    // Publish this to Azure logging account so that a web dashboard can see it. 
                    await LogHostStartedAsync(functions, hostOutputMessage, hostInstanceLogger, combinedCancellationToken);
                }
                else
                {
                    hostCallExecutor = new ShutdownFunctionExecutor(shutdownToken, functionExecutor);

                    IListener factoryListener = new ListenerFactoryListener(functionsListenerFactory);
                    IListener shutdownListener = new ShutdownListener(shutdownToken, factoryListener);
                    listener = shutdownListener;

                    hostOutputMessage = new DataOnlyHostOutputMessage();
                }

                functionExecutor.HostOutputMessage = hostOutputMessage;

                IEnumerable<FunctionDescriptor> descriptors = functions.ReadAllDescriptors();
                int descriptorsCount = descriptors.Count();

                if (descriptorsCount == 0)
                {
                    trace.Warning("No functions found. Try making job classes and methods public.", TraceSource.Indexing);
                }
                else
                {
                    StringBuilder functionsTrace = new StringBuilder();
                    functionsTrace.AppendLine("Found the following functions:");
                    
                    foreach (FunctionDescriptor descriptor in descriptors)
                    {
                        functionsTrace.AppendLine(descriptor.FullName);
                    }

                    trace.Info(functionsTrace.ToString(), TraceSource.Indexing);
                }

                return new JobHostContext(functions, hostCallExecutor, listener, trace);
            }
        }
 public static async Task <IStorageAccount> GetStorageAccountAsync(this IStorageAccountProvider provider, IConnectionProvider connectionProvider, CancellationToken cancellationToken, INameResolver nameResolver = null)
 {
     return(await provider.GetStorageAccountAsync(connectionProvider.Connection, cancellationToken, nameResolver));
 }