public SingletonManagerTests() { _mockAccountProvider = new Mock <IStorageAccountProvider>(MockBehavior.Strict); _mockBlobDirectory = new Mock <IStorageBlobDirectory>(MockBehavior.Strict); _mockSecondaryBlobDirectory = new Mock <IStorageBlobDirectory>(MockBehavior.Strict); _mockStorageAccount = new Mock <IStorageAccount>(MockBehavior.Strict); _mockStorageAccount.SetupGet(a => a.Type).Returns(StorageAccountType.GeneralPurpose); _mockSecondaryStorageAccount = new Mock <IStorageAccount>(MockBehavior.Strict); _mockSecondaryStorageAccount.SetupGet(a => a.Type).Returns(StorageAccountType.GeneralPurpose); Mock <IStorageBlobClient> mockBlobClient = new Mock <IStorageBlobClient>(MockBehavior.Strict); Mock <IStorageBlobClient> mockSecondaryBlobClient = new Mock <IStorageBlobClient>(MockBehavior.Strict); Mock <IStorageBlobContainer> mockBlobContainer = new Mock <IStorageBlobContainer>(MockBehavior.Strict); mockBlobContainer.Setup(p => p.GetDirectoryReference(HostDirectoryNames.SingletonLocks)).Returns(_mockBlobDirectory.Object); mockBlobClient.Setup(p => p.GetContainerReference(HostContainerNames.Hosts)).Returns(mockBlobContainer.Object); Mock <IStorageBlobContainer> mockSecondaryBlobContainer = new Mock <IStorageBlobContainer>(MockBehavior.Strict); mockSecondaryBlobContainer.Setup(p => p.GetDirectoryReference(HostDirectoryNames.SingletonLocks)).Returns(_mockSecondaryBlobDirectory.Object); mockSecondaryBlobClient.Setup(p => p.GetContainerReference(HostContainerNames.Hosts)).Returns(mockSecondaryBlobContainer.Object); _mockStorageAccount.Setup(p => p.CreateBlobClient(null)).Returns(mockBlobClient.Object); _mockSecondaryStorageAccount.Setup(p => p.CreateBlobClient(null)).Returns(mockSecondaryBlobClient.Object); _mockAccountProvider.Setup(p => p.TryGetAccountAsync(ConnectionStringNames.Storage, It.IsAny <CancellationToken>())) .ReturnsAsync(_mockStorageAccount.Object); _mockAccountProvider.Setup(p => p.TryGetAccountAsync(Secondary, It.IsAny <CancellationToken>())) .ReturnsAsync(_mockSecondaryStorageAccount.Object); _mockExceptionDispatcher = new Mock <IWebJobsExceptionHandler>(MockBehavior.Strict); _mockStorageBlob = new Mock <IStorageBlockBlob>(MockBehavior.Strict); _mockBlobMetadata = new Dictionary <string, string>(); _mockBlobDirectory.Setup(p => p.GetBlockBlobReference(TestLockId)).Returns(_mockStorageBlob.Object); _singletonConfig = new SingletonConfiguration(); // use reflection to bypass the normal validations (so tests can run fast) TestHelpers.SetField(_singletonConfig, "_lockAcquisitionPollingInterval", TimeSpan.FromMilliseconds(25)); TestHelpers.SetField(_singletonConfig, "_lockPeriod", TimeSpan.FromMilliseconds(500)); _singletonConfig.LockAcquisitionTimeout = TimeSpan.FromMilliseconds(200); _nameResolver = new TestNameResolver(); ILoggerFactory loggerFactory = new LoggerFactory(); // We want to see all logs, so set the default level to Trace. LogCategoryFilter filter = new LogCategoryFilter { DefaultLevel = Extensions.Logging.LogLevel.Trace }; _loggerProvider = new TestLoggerProvider(filter.Filter); loggerFactory.AddProvider(_loggerProvider); var logger = loggerFactory?.CreateLogger(LogCategories.Singleton); _core = new BlobLeaseDistributedLockManager.DedicatedStorage(_mockAccountProvider.Object, logger); _singletonManager = new SingletonManager(_core, _singletonConfig, _mockExceptionDispatcher.Object, loggerFactory, new FixedHostIdProvider(TestHostId), _nameResolver); _singletonManager.MinimumLeaseRenewalInterval = TimeSpan.FromMilliseconds(250); }
// Static initialization. Returns a service provider with some new services initialized. // The new services: // - can retrieve static config like binders and converters; but the listeners haven't yet started. // - can be flowed into the runtime initialization to get a JobHost spun up and running. // This is just static initialization and should not need to make any network calls, // and so this method should not need to be async. // This can be called multiple times on a config, which is why it returns a new ServiceProviderWrapper // instead of modifying the config. public static ServiceProviderWrapper CreateStaticServices(this JobHostConfiguration config) { var services = new ServiceProviderWrapper(config); var consoleProvider = services.GetService <IConsoleProvider>(); var nameResolver = services.GetService <INameResolver>(); IWebJobsExceptionHandler exceptionHandler = services.GetService <IWebJobsExceptionHandler>(); IQueueConfiguration queueConfiguration = services.GetService <IQueueConfiguration>(); var blobsConfiguration = config.Blobs; IStorageAccountProvider storageAccountProvider = services.GetService <IStorageAccountProvider>(); IBindingProvider bindingProvider = services.GetService <IBindingProvider>(); SingletonManager singletonManager = services.GetService <SingletonManager>(); IHostIdProvider hostIdProvider = services.GetService <IHostIdProvider>(); var hostId = config.HostId; if (hostId != null) { hostIdProvider = new FixedHostIdProvider(hostId); } // Need a deferred getter since the IFunctionIndexProvider service isn't created until later. Func <IFunctionIndexProvider> deferredGetter = () => services.GetService <IFunctionIndexProvider>(); if (hostIdProvider == null) { hostIdProvider = new DynamicHostIdProvider(storageAccountProvider, deferredGetter); } services.AddService <IHostIdProvider>(hostIdProvider); AzureStorageDeploymentValidator.Validate(); IExtensionTypeLocator extensionTypeLocator = services.GetService <IExtensionTypeLocator>(); if (extensionTypeLocator == null) { extensionTypeLocator = new ExtensionTypeLocator(services.GetService <ITypeLocator>()); services.AddService <IExtensionTypeLocator>(extensionTypeLocator); } ContextAccessor <IMessageEnqueuedWatcher> messageEnqueuedWatcherAccessor = new ContextAccessor <IMessageEnqueuedWatcher>(); services.AddService(messageEnqueuedWatcherAccessor); ContextAccessor <IBlobWrittenWatcher> blobWrittenWatcherAccessor = new ContextAccessor <IBlobWrittenWatcher>(); ISharedContextProvider sharedContextProvider = new SharedContextProvider(); // Create a wrapper TraceWriter that delegates to both the user // TraceWriters specified via config (if present), as well as to Console TraceWriter trace = new ConsoleTraceWriter(config.Tracing, consoleProvider.Out); services.AddService <TraceWriter>(trace); // Add built-in extensions var metadataProvider = new JobHostMetadataProvider(deferredGetter); metadataProvider.AddAttributesFromAssembly(typeof(TableAttribute).Assembly); var exts = config.GetExtensions(); bool builtinsAdded = exts.GetExtensions <IExtensionConfigProvider>().OfType <TableExtension>().Any(); if (!builtinsAdded) { config.AddExtension(new TableExtension()); config.AddExtension(new QueueExtension()); } ExtensionConfigContext context = new ExtensionConfigContext { Config = config, Trace = trace, PerHostServices = services }; InvokeExtensionConfigProviders(context); // After this point, all user configuration has been set. if (singletonManager == null) { var logger = config.LoggerFactory?.CreateLogger(LogCategories.Singleton); IDistributedLockManager lockManager = services.GetService <IDistributedLockManager>(); if (lockManager == null) { lockManager = new BlobLeaseDistributedLockManager( storageAccountProvider, trace, logger); services.AddService <IDistributedLockManager>(lockManager); } singletonManager = new SingletonManager( lockManager, config.Singleton, trace, exceptionHandler, config.LoggerFactory, hostIdProvider, services.GetService <INameResolver>()); services.AddService <SingletonManager>(singletonManager); } IExtensionRegistry extensions = services.GetExtensions(); ITriggerBindingProvider triggerBindingProvider = DefaultTriggerBindingProvider.Create(nameResolver, storageAccountProvider, extensionTypeLocator, hostIdProvider, queueConfiguration, blobsConfiguration, exceptionHandler, messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, sharedContextProvider, extensions, singletonManager, trace, config.LoggerFactory); services.AddService <ITriggerBindingProvider>(triggerBindingProvider); if (bindingProvider == null) { bindingProvider = DefaultBindingProvider.Create(nameResolver, config.LoggerFactory, storageAccountProvider, extensionTypeLocator, blobWrittenWatcherAccessor, extensions); services.AddService <IBindingProvider>(bindingProvider); } var converterManager = (ConverterManager)config.ConverterManager; metadataProvider.Initialize(bindingProvider, converterManager, exts); services.AddService <IJobHostMetadataProvider>(metadataProvider); return(services); }