public async Task TryPutToCache_VerifyResultMatchesResultOfCacheOperation(bool expected) { // Arrange Mock <SharedMemoryMetadata> sharedMemMetaMock = CreateMockSharedMemoryMetadata(); SharedMemoryMetadata sharedMemMeta = sharedMemMetaMock.Object; bool isIncrementActiveRefs = false; bool isDeleteOnFailure = false; Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); cacheMock .Setup(c => c.TryPut(It.IsAny <FunctionDataCacheKey>(), sharedMemMeta, isIncrementActiveRefs, isDeleteOnFailure)) .Returns(expected) .Verifiable(); IFunctionDataCache cache = cacheMock.Object; BlobWithContainer <BlobBaseClient> blob = CreateBlobReference(ContainerName, "blob"); Mock <Stream> mockBlobStream = CreateMockBlobStream(); Stream blobStream = mockBlobStream.Object; CacheableWriteBlob cacheableWriteBlob = CreateProductUnderTest(blob, sharedMemMeta, blobStream, cache); // Act bool result = await cacheableWriteBlob.TryPutToCacheAsync(isDeleteOnFailure); // Assert Assert.AreEqual(expected, result); cacheMock.Verify(); }
/// <summary> /// </summary> /// <param name="blob">Blob for this object in storage.</param> /// <param name="cacheObject">Describes the shared memory region containing this object.</param> /// <param name="blobStream">Stream to use for writing this object to storage.</param> /// <param name="functionDataCache">Cache in which to put this object when required.</param> public CacheableWriteBlob(BlobWithContainer <BlobBaseClient> blob, SharedMemoryMetadata cacheObject, Stream blobStream, IFunctionDataCache functionDataCache) { BlobStream = blobStream; _cacheObject = cacheObject; _functionDataCache = functionDataCache; _blob = blob; }
public MockCacheAwareReadObject(FunctionDataCacheKey cacheKey, SharedMemoryMetadata cacheObject, IFunctionDataCache functionDataCache) { _functionDataCache = functionDataCache; CacheKey = cacheKey; CacheObject = cacheObject; IsCacheHit = true; }
public void TryPutToCache_VerifySuccess(bool expected) { // Arrange FunctionDataCacheKey key = CreateFunctionDataCacheKey(); bool isIncrementActiveRefs = true; Mock <SharedMemoryMetadata> sharedMemMetaMock = CreateMockSharedMemoryMetadata(); SharedMemoryMetadata sharedMemMeta = sharedMemMetaMock.Object; Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); cacheMock .Setup(c => c.TryPut(key, sharedMemMeta, isIncrementActiveRefs, false)) .Returns(expected) .Verifiable(); IFunctionDataCache cache = cacheMock.Object; Mock <Stream> blobStreamMock = CreateMockBlobStream(); Stream blobStream = blobStreamMock.Object; CacheableReadBlob cacheableReadBlob = CreateProductUnderTest(key, blobStream, cache); // Act bool result = cacheableReadBlob.TryPutToCache(sharedMemMeta, isIncrementActiveRefs); // Assert Assert.AreEqual(expected, result); cacheMock.Verify(); }
public MockCacheAwareReadObject(FunctionDataCacheKey cacheKey, Stream blobStream, IFunctionDataCache functionDataCache) { _functionDataCache = functionDataCache; CacheKey = cacheKey; BlobStream = blobStream; IsCacheHit = false; }
/// <summary> /// Used when the object was found in the cache. /// </summary> /// <param name="cacheKey">Key associated to this object to address it in the <see cref="IFunctionDataCache"/>.</param> /// <param name="cacheObject">Describes the shared memory region containing this object.</param> /// <param name="functionDataCache">Cache in which to put this object when required.</param> public CacheableReadBlob(FunctionDataCacheKey cacheKey, SharedMemoryMetadata cacheObject, IFunctionDataCache functionDataCache) { IsCacheHit = true; CacheKey = cacheKey; CacheObject = cacheObject; _functionDataCache = functionDataCache; _isDisposed = false; _decrementRefCountInCacheOnDispose = true; }
/// <summary> /// Used when the object was not found in the cache and will be retrieved from storage. /// </summary> /// <param name="cacheKey">Key associated to this object to address it in the <see cref="IFunctionDataCache"/>.</param> /// <param name="blobStream">Stream to use for writing this object to storage.</param> /// <param name="functionDataCache">Cache in which to put this object when required.</param> public CacheableReadBlob(FunctionDataCacheKey cacheKey, Stream blobStream, IFunctionDataCache functionDataCache) { IsCacheHit = false; CacheKey = cacheKey; BlobStream = blobStream; _functionDataCache = functionDataCache; _isDisposed = false; _decrementRefCountInCacheOnDispose = false; }
public GrpcWorkerChannelTests() { _logger = new TestLogger("FunctionDispatcherTests"); _testFunctionRpcService = new TestFunctionRpcService(_eventManager, _workerId, _logger, _expectedLogMsg); _testWorkerConfig = TestHelpers.GetTestWorkerConfigs().FirstOrDefault(); _testWorkerConfig.CountOptions.ProcessStartupTimeout = TimeSpan.FromSeconds(5); _testWorkerConfig.CountOptions.InitializationTimeout = TimeSpan.FromSeconds(5); _testWorkerConfig.CountOptions.EnvironmentReloadTimeout = TimeSpan.FromSeconds(5); _mockrpcWorkerProcess.Setup(m => m.StartProcessAsync()).Returns(Task.CompletedTask); _mockrpcWorkerProcess.Setup(m => m.Id).Returns(910); _testEnvironment = new TestEnvironment(); _testEnvironment.SetEnvironmentVariable(FunctionDataCacheConstants.FunctionDataCacheEnabledSettingName, "1"); _workerConcurrencyOptions = Options.Create(new WorkerConcurrencyOptions()); _workerConcurrencyOptions.Value.CheckInterval = TimeSpan.FromSeconds(1); ILogger <MemoryMappedFileAccessor> mmapAccessorLogger = NullLogger <MemoryMappedFileAccessor> .Instance; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { _mapAccessor = new MemoryMappedFileAccessorWindows(mmapAccessorLogger); } else { _mapAccessor = new MemoryMappedFileAccessorUnix(mmapAccessorLogger, _testEnvironment); } _sharedMemoryManager = new SharedMemoryManager(_loggerFactory, _mapAccessor); _functionDataCache = new FunctionDataCache(_sharedMemoryManager, _loggerFactory, _testEnvironment); var hostOptions = new ScriptApplicationHostOptions { IsSelfHost = true, ScriptPath = _scriptRootPath, LogPath = Environment.CurrentDirectory, // not tested SecretsPath = Environment.CurrentDirectory, // not tested HasParentScope = true }; _hostOptionsMonitor = TestHelpers.CreateOptionsMonitor(hostOptions); _workerChannel = new GrpcWorkerChannel( _workerId, _eventManager, _testWorkerConfig, _mockrpcWorkerProcess.Object, _logger, _metricsLogger, 0, _testEnvironment, _hostOptionsMonitor, _sharedMemoryManager, _functionDataCache, _workerConcurrencyOptions); }
internal GrpcWorkerChannel( string workerId, IScriptEventManager eventManager, RpcWorkerConfig workerConfig, IWorkerProcess rpcWorkerProcess, ILogger logger, IMetricsLogger metricsLogger, int attemptCount, IEnvironment environment, IOptionsMonitor <ScriptApplicationHostOptions> applicationHostOptions, ISharedMemoryManager sharedMemoryManager, IFunctionDataCache functionDataCache, IOptions <WorkerConcurrencyOptions> workerConcurrencyOptions) { _workerId = workerId; _eventManager = eventManager; _workerConfig = workerConfig; _runtime = workerConfig.Description.Language; _rpcWorkerProcess = rpcWorkerProcess; _workerChannelLogger = logger; _metricsLogger = metricsLogger; _environment = environment; _applicationHostOptions = applicationHostOptions; _sharedMemoryManager = sharedMemoryManager; _workerConcurrencyOptions = workerConcurrencyOptions; _workerCapabilities = new GrpcCapabilities(_workerChannelLogger); _inboundWorkerEvents = _eventManager.OfType <InboundGrpcEvent>() .Where(msg => msg.WorkerId == _workerId); _eventSubscriptions.Add(_inboundWorkerEvents .Where(msg => msg.IsMessageOfType(MsgType.RpcLog) && !msg.IsLogOfCategory(RpcLogCategory.System)) .Subscribe(Log)); _eventSubscriptions.Add(_inboundWorkerEvents .Where(msg => msg.IsMessageOfType(MsgType.RpcLog) && msg.IsLogOfCategory(RpcLogCategory.System)) .Subscribe(SystemLog)); _eventSubscriptions.Add(_eventManager.OfType <FileEvent>() .Where(msg => _workerConfig.Description.Extensions.Contains(Path.GetExtension(msg.FileChangeArguments.FullPath))) .Throttle(TimeSpan.FromMilliseconds(300)) // debounce .Subscribe(msg => _eventManager.Publish(new HostRestartEvent()))); _eventSubscriptions.Add(_inboundWorkerEvents.Where(msg => msg.MessageType == MsgType.InvocationResponse) .Subscribe(async(msg) => await InvokeResponse(msg.Message.InvocationResponse))); _inboundWorkerEvents.Where(msg => msg.MessageType == MsgType.WorkerStatusResponse) .Subscribe((msg) => ReceiveWorkerStatusResponse(msg.Message.RequestId, msg.Message.WorkerStatusResponse)); _startLatencyMetric = metricsLogger?.LatencyEvent(string.Format(MetricEventNames.WorkerInitializeLatency, workerConfig.Description.Language, attemptCount)); _state = RpcWorkerChannelState.Default; }
public GrpcWorkerChannelFactory(IScriptEventManager eventManager, IEnvironment environment, IRpcServer rpcServer, ILoggerFactory loggerFactory, IOptionsMonitor <LanguageWorkerOptions> languageWorkerOptions, IOptionsMonitor <ScriptApplicationHostOptions> applicationHostOptions, IRpcWorkerProcessFactory rpcWorkerProcessManager, ISharedMemoryManager sharedMemoryManager, IFunctionDataCache functionDataCache, IOptions <WorkerConcurrencyOptions> workerConcurrencyOptions) { _eventManager = eventManager; _loggerFactory = loggerFactory; _rpcWorkerProcessFactory = rpcWorkerProcessManager; _environment = environment; _applicationHostOptions = applicationHostOptions; _sharedMemoryManager = sharedMemoryManager; _functionDataCache = functionDataCache; _workerConcurrencyOptions = workerConcurrencyOptions; }
public void CreateCacheableReadBlob_IsCacheHit() { // Arrange FunctionDataCacheKey key = CreateFunctionDataCacheKey(); Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); IFunctionDataCache cache = cacheMock.Object; Mock <SharedMemoryMetadata> sharedMemMetaMock = CreateMockSharedMemoryMetadata(); SharedMemoryMetadata sharedMemMeta = sharedMemMetaMock.Object; CacheableReadBlob cacheableReadBlob = CreateProductUnderTest(key, sharedMemMeta, cache); // Act bool isCacheHit = cacheableReadBlob.IsCacheHit; // Assert Assert.True(isCacheHit); }
public void CreateCacheableReadBlob_IsCacheMiss() { // Arrange FunctionDataCacheKey key = CreateFunctionDataCacheKey(); Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); IFunctionDataCache cache = cacheMock.Object; Mock <Stream> blobStreamMock = CreateMockBlobStream(); Stream blobStream = blobStreamMock.Object; CacheableReadBlob cacheableReadBlob = CreateProductUnderTest(key, blobStream, cache); // Act bool isCacheHit = cacheableReadBlob.IsCacheHit; // Assert Assert.False(isCacheHit); }
public async Task InitializeAsync(WebJobsTestEnvironment testEnvironment) { RandomNameResolver nameResolver = new RandomNameResolver(); CacheMock = CreateMockFunctionDataCache(); CacheMock .Setup(c => c.IsEnabled) .Returns(true); IFunctionDataCache cache = CacheMock.Object; Host = new HostBuilder() .ConfigureDefaultTestHost <CacheableBlobsEndToEndTests>(b => { b.AddAzureStorageBlobs().AddAzureStorageQueues(); b.AddAzureStorageCoreServices(); }) .ConfigureServices(services => { services.AddSingleton <INameResolver>(nameResolver) .AddSingleton(cache); }) .Build(); JobHost = Host.GetJobHost(); BlobServiceClient = new BlobServiceClient(testEnvironment.PrimaryStorageAccountConnectionString); BlobContainer = BlobServiceClient.GetBlobContainerClient(nameResolver.ResolveInString(ContainerName)); Assert.False(await BlobContainer.ExistsAsync()); await BlobContainer.CreateAsync(); OutputBlobContainer = BlobServiceClient.GetBlobContainerClient(nameResolver.ResolveInString(OutputContainerName)); await Host.StartAsync(); // Upload some test blobs BlockBlobClient blob = BlobContainer.GetBlockBlobClient(InputBlobName); await blob.UploadTextAsync(TestData); // Get information about the uploaded blob BlobProperties blobProperties = await blob.GetPropertiesAsync(); string blobId = blob.Uri.ToString(); string blobVersion = blobProperties.ETag.ToString(); _expectedBlobCacheKey = new FunctionDataCacheKey(blobId, blobVersion); }
public ScriptInvocationContextExtensionsTests() { ILogger <MemoryMappedFileAccessor> logger = NullLogger <MemoryMappedFileAccessor> .Instance; _testEnvironment = new TestEnvironment(); _testEnvironment.SetEnvironmentVariable(FunctionDataCacheConstants.FunctionDataCacheEnabledSettingName, "1"); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { _mapAccessor = new MemoryMappedFileAccessorWindows(logger); } else { _mapAccessor = new MemoryMappedFileAccessorUnix(logger, _testEnvironment); } _sharedMemoryManager = new SharedMemoryManager(_loggerFactory, _mapAccessor); _functionDataCache = new FunctionDataCache(_sharedMemoryManager, _loggerFactory, _testEnvironment); }
public void TryPutToCacheAlreadyCached_VerifyFailure() { // Arrange FunctionDataCacheKey key = CreateFunctionDataCacheKey(); bool isIncrementActiveRefs = true; Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); cacheMock .Setup(c => c.TryPut(key, It.IsAny <SharedMemoryMetadata>(), isIncrementActiveRefs, false)) .Throws(new Exception("This should not be called")); IFunctionDataCache cache = cacheMock.Object; Mock <SharedMemoryMetadata> sharedMemMetaMock = CreateMockSharedMemoryMetadata(); SharedMemoryMetadata sharedMemMeta = sharedMemMetaMock.Object; CacheableReadBlob cacheableReadBlob = CreateProductUnderTest(key, sharedMemMeta, cache); // Act bool result = cacheableReadBlob.TryPutToCache(sharedMemMeta, isIncrementActiveRefs); // Assert Assert.IsFalse(result); }
public BlobsExtensionConfigProvider( BlobServiceClientProvider blobServiceClientProvider, BlobTriggerAttributeBindingProvider triggerBinder, IContextGetter <IBlobWrittenWatcher> contextAccessor, INameResolver nameResolver, IConverterManager converterManager, BlobTriggerQueueWriterFactory blobTriggerQueueWriterFactory, HttpRequestProcessor httpRequestProcessor, IFunctionDataCache functionDataCache, ILoggerFactory loggerFactory) { _blobServiceClientProvider = blobServiceClientProvider; _triggerBinder = triggerBinder; _blobWrittenWatcherGetter = contextAccessor; _nameResolver = nameResolver; _converterManager = converterManager; _blobTriggerQueueWriterFactory = blobTriggerQueueWriterFactory; _httpRequestProcessor = httpRequestProcessor; _functionDataCache = functionDataCache; _logger = loggerFactory.CreateLogger <BlobsExtensionConfigProvider>(); }
public void CacheHit_Dispose_VerifyCacheRefCountDecremented() { // Arrange FunctionDataCacheKey key = CreateFunctionDataCacheKey(); Mock <SharedMemoryMetadata> sharedMemMetaMock = CreateMockSharedMemoryMetadata(); SharedMemoryMetadata sharedMemMeta = sharedMemMetaMock.Object; Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); cacheMock .Setup(c => c.DecrementActiveReference(key)) .Verifiable(); IFunctionDataCache cache = cacheMock.Object; CacheableReadBlob cacheableReadBlob = CreateProductUnderTest(key, sharedMemMeta, cache); // Act cacheableReadBlob.Dispose(); // Assert // This will ensure that the appropriate method was called on the cache cacheMock.Verify(); }
public async Task TryPutToCache_CacheObjectNull_VerifyFailure() { // Arrange bool isIncrementActiveRefs = false; bool isDeleteOnFailure = false; Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); cacheMock .Setup(c => c.TryPut(It.IsAny <FunctionDataCacheKey>(), It.IsAny <SharedMemoryMetadata>(), isIncrementActiveRefs, isDeleteOnFailure)) .Throws(new Exception("This should not be called")); IFunctionDataCache cache = cacheMock.Object; BlobWithContainer <BlobBaseClient> blob = CreateBlobReference(ContainerName, "blob"); Mock <Stream> mockBlobStream = CreateMockBlobStream(); Stream blobStream = mockBlobStream.Object; CacheableWriteBlob cacheableWriteBlob = CreateProductUnderTest(blob, null, blobStream, cache); // Act bool result = await cacheableWriteBlob.TryPutToCacheAsync(isDeleteOnFailure); // Assert Assert.IsFalse(result); }
public void CacheMiss_Dispose_VerifyBlobStreamDisposed() { // Arrange FunctionDataCacheKey key = CreateFunctionDataCacheKey(); Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); IFunctionDataCache cache = cacheMock.Object; Mock <SharedMemoryMetadata> sharedMemMetaMock = CreateMockSharedMemoryMetadata(); SharedMemoryMetadata sharedMemMeta = sharedMemMetaMock.Object; Mock <Stream> blobStreamMock = CreateMockBlobStream(); blobStreamMock .Setup(s => s.Close()) // Close is called internally when Stream is Disposed .Verifiable(); Stream blobStream = blobStreamMock.Object; CacheableReadBlob cacheableReadBlob = CreateProductUnderTest(key, blobStream, cache); // Act cacheableReadBlob.Dispose(); // Assert // This will ensure that the appropriate method was called on the stream blobStreamMock.Verify(); }
public void CacheMiss_Dispose_VerifyCacheRefCountNotDecremented() { // Arrange FunctionDataCacheKey key = CreateFunctionDataCacheKey(); Mock <IFunctionDataCache> cacheMock = CreateMockFunctionDataCache(); cacheMock .Setup(c => c.DecrementActiveReference(key)) .Throws(new Exception("This should not be called")); IFunctionDataCache cache = cacheMock.Object; Mock <Stream> blobStreamMock = CreateMockBlobStream(); blobStreamMock .Setup(s => s.Close()) .Verifiable(); Stream blobStream = blobStreamMock.Object; CacheableReadBlob cacheableReadBlob = CreateProductUnderTest(key, blobStream, cache); // Act cacheableReadBlob.Dispose(); // Assert // If the wrong method was called, an exception would have been thrown }
/// <summary> /// Create a <see cref="CacheableReadBlob"/> to use for a test. /// </summary> /// <param name="cacheKey">Key associated to this object to address it in the <see cref="IFunctionDataCache"/>.</param> /// <param name="blobStream">Stream to use for writing this object to storage.</param> /// <param name="functionDataCache">Cache in which to put this object when required.</param> /// <returns>A <see cref="CacheableReadBlob"/> object to use for a test.</returns> private static CacheableReadBlob CreateProductUnderTest(FunctionDataCacheKey cacheKey, SharedMemoryMetadata sharedMemMeta, IFunctionDataCache functionDataCache) { return(new CacheableReadBlob(cacheKey, sharedMemMeta, functionDataCache)); }
/// <summary> /// Create a <see cref="CacheableReadBlob"/> to use for a test. /// </summary> /// <param name="cacheKey">Key associated to this object to address it in the <see cref="IFunctionDataCache"/>.</param> /// <param name="blobStream">Stream to use for writing this object to storage.</param> /// <param name="functionDataCache">Cache in which to put this object when required.</param> /// <returns>A <see cref="CacheableReadBlob"/> object to use for a test.</returns> private static CacheableReadBlob CreateProductUnderTest(FunctionDataCacheKey cacheKey, Stream blobStream, IFunctionDataCache functionDataCache) { return(new CacheableReadBlob(cacheKey, blobStream, functionDataCache)); }
public static async Task <ICacheAwareReadObject> TryBindCacheAwareAsync(BlobWithContainer <BlobBaseClient> blob, ValueBindingContext context, IFunctionDataCache functionDataCache) { try { // Generate the cache key for this blob FunctionDataCacheKey cacheKey = await GetFunctionDataCacheKey(blob, context.CancellationToken).ConfigureAwait(false); if (cacheKey == null) { return(null); } // Check if it exists in the cache if (functionDataCache.TryGet(cacheKey, isIncrementActiveReference: true, out SharedMemoryMetadata sharedMemoryMeta)) { // CACHE HIT return(new CacheableReadBlob(cacheKey, sharedMemoryMeta, functionDataCache)); } // CACHE MISS // Wrap the blob's stream along with the cache key so it can be inserted in the cache later using the above generated key for this blob Stream innerStream = await TryBindStreamAsync(blob.BlobClient, context.CancellationToken, cacheKey.Version).ConfigureAwait(false); return(new CacheableReadBlob(cacheKey, innerStream, functionDataCache)); } catch (RequestFailedException exception) { // Testing generic error case since specific error codes are not available for FetchAttributes // (HEAD request), including OpenRead. if (!exception.IsNotFound()) { throw; } return(null); } }
public static async Task <ICacheAwareWriteObject> BindStreamCacheAwareAsync(BlobWithContainer <BlobBaseClient> blob, ValueBindingContext context, IBlobWrittenWatcher blobWrittenWatcher, IFunctionDataCache functionDataCache) { Stream blobStream = await BindStreamAsync(blob, context, blobWrittenWatcher).ConfigureAwait(false); return(new CacheableWriteBlob(blob, context.SharedMemoryMetadata, blobStream, functionDataCache)); }
/// <summary> /// Create a <see cref="CacheableWriteBlob"/> to use for a test. /// </summary> /// <param name="blob">Blob for this object in storage.</param> /// <param name="cacheObject">Describes the shared memory region containing this object.</param> /// <param name="blobStream">Stream to use for writing this object to storage.</param> /// <param name="functionDataCache">Cache in which to put this object when required.</param> /// <returns>A <see cref="CacheableWriteBlob"/> object to use for a test.</returns> private static CacheableWriteBlob CreateProductUnderTest(BlobWithContainer <BlobBaseClient> blob, SharedMemoryMetadata cacheObject, Stream blobStream, IFunctionDataCache functionDataCache) { return(new CacheableWriteBlob(blob, cacheObject, blobStream, functionDataCache)); }
// Specify the "builtin binding types". These are types that are directly accesible without needing an explicit load gesture. // This is the set of bindings we shipped prior to binding extensibility. // Map from BindingType to the Assembly Qualified Type name for its IExtensionConfigProvider object. public ScriptHost(IOptions <JobHostOptions> options, IOptions <HttpWorkerOptions> httpWorkerOptions, IEnvironment environment, IJobHostContextFactory jobHostContextFactory, IConfiguration configuration, IDistributedLockManager distributedLockManager, IScriptEventManager eventManager, ILoggerFactory loggerFactory, IFunctionInvocationDispatcherFactory functionDispatcherFactory, IFunctionMetadataManager functionMetadataManager, IFileLoggingStatusManager fileLoggingStatusManager, IMetricsLogger metricsLogger, IOptions <ScriptJobHostOptions> scriptHostOptions, ITypeLocator typeLocator, IScriptHostManager scriptHostManager, IDebugStateProvider debugManager, IEnumerable <IScriptBindingProvider> bindingProviders, IPrimaryHostStateProvider primaryHostStateProvider, IJobHostMetadataProvider metadataProvider, IHostIdProvider hostIdProvider, IHttpRoutesManager httpRoutesManager, IApplicationLifetime applicationLifetime, IExtensionBundleManager extensionBundleManager, IFunctionDataCache functionDataCache, IOptions <LanguageWorkerOptions> languageWorkerOptions, ScriptSettingsManager settingsManager = null) : base(options, jobHostContextFactory) { _environment = environment; _typeLocator = typeLocator as ScriptTypeLocator ?? throw new ArgumentException(nameof(typeLocator), $"A {nameof(ScriptTypeLocator)} instance is required."); _instanceId = Guid.NewGuid().ToString(); _hostOptions = options; _configuration = configuration; _distributedLockManager = distributedLockManager; _functionMetadataManager = functionMetadataManager; _fileLoggingStatusManager = fileLoggingStatusManager; _applicationLifetime = applicationLifetime; _hostIdProvider = hostIdProvider; _httpRoutesManager = httpRoutesManager; _isHttpWorker = httpWorkerOptions.Value.Description != null; _httpWorkerOptions = httpWorkerOptions.Value; ScriptOptions = scriptHostOptions.Value; _scriptHostManager = scriptHostManager; FunctionErrors = new Dictionary <string, ICollection <string> >(StringComparer.OrdinalIgnoreCase); EventManager = eventManager; _functionDispatcher = functionDispatcherFactory.GetFunctionDispatcher(); _settingsManager = settingsManager ?? ScriptSettingsManager.Instance; ExtensionBundleManager = extensionBundleManager; _metricsLogger = metricsLogger; _hostLogPath = Path.Combine(ScriptOptions.RootLogPath, "Host"); _workerRuntime = _environment.GetEnvironmentVariable(RpcWorkerConstants.FunctionWorkerRuntimeSettingName); _languageWorkerOptions = languageWorkerOptions; _loggerFactory = loggerFactory; _logger = loggerFactory.CreateLogger(LogCategories.Startup); Logger = _logger; _debugManager = debugManager; _primaryHostStateProvider = primaryHostStateProvider; _bindingProviders = new List <IScriptBindingProvider>(bindingProviders); _metadataProvider = metadataProvider; _eventSubscriptions.Add(EventManager.OfType <FunctionIndexingEvent>() .Subscribe(evt => { HandleHostError(evt.Exception); })); _functionDataCache = functionDataCache; }