public ControlPlaneDataStore( IScoped<IDocumentClient> documentClient, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, ICosmosDocumentQueryFactory cosmosDocumentQueryFactory, RetryExceptionPolicyFactory retryExceptionPolicyFactory, IOptionsMonitor<CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, ILogger<ControlPlaneDataStore> logger) { EnsureArg.IsNotNull(documentClient, nameof(documentClient)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(cosmosDocumentQueryFactory, nameof(cosmosDocumentQueryFactory)); EnsureArg.IsNotNull(retryExceptionPolicyFactory, nameof(retryExceptionPolicyFactory)); EnsureArg.IsNotNull(namedCosmosCollectionConfigurationAccessor, nameof(namedCosmosCollectionConfigurationAccessor)); EnsureArg.IsNotNull(logger, nameof(logger)); var collectionConfig = namedCosmosCollectionConfigurationAccessor.Get(Constants.CollectionConfigurationName); _documentClient = documentClient; _collectionUri = cosmosDataStoreConfiguration.GetRelativeCollectionUri(collectionConfig.CollectionId); _retryExceptionPolicyFactory = retryExceptionPolicyFactory; _cosmosDocumentQueryFactory = cosmosDocumentQueryFactory; _logger = logger; _hardDeleteIdentityProvider = new HardDeleteIdentityProvider(); _hardDeleteRole = new HardDeleteRole(); }
/// <inheritdoc /> public async Task InitializeDataStore(CosmosClient client, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, IEnumerable <ICollectionInitializer> collectionInitializers) { EnsureArg.IsNotNull(client, nameof(client)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(collectionInitializers, nameof(collectionInitializers)); try { _logger.LogInformation("Initializing Cosmos DB Database {DatabaseId} and collections", cosmosDataStoreConfiguration.DatabaseId); if (cosmosDataStoreConfiguration.AllowDatabaseCreation) { _logger.LogInformation("CreateDatabaseIfNotExists {DatabaseId}", cosmosDataStoreConfiguration.DatabaseId); await client.CreateDatabaseIfNotExistsAsync( cosmosDataStoreConfiguration.DatabaseId, cosmosDataStoreConfiguration.InitialDatabaseThroughput.HasValue?ThroughputProperties.CreateManualThroughput(cosmosDataStoreConfiguration.InitialDatabaseThroughput.Value) : null); } foreach (var collectionInitializer in collectionInitializers) { await collectionInitializer.InitializeCollection(client); } _logger.LogInformation("Cosmos DB Database {DatabaseId} and collections successfully initialized", cosmosDataStoreConfiguration.DatabaseId); } catch (Exception ex) { _logger.LogCritical(ex, "Cosmos DB Database {DatabaseId} and collections initialization failed", cosmosDataStoreConfiguration.DatabaseId); throw; } }
/// <summary> /// Initializes a new instance of the <see cref="FhirDataStore"/> class. /// </summary> /// <param name="documentClient"> /// A function that returns an <see cref="IDocumentClient"/>. /// Note that this is a function so that the lifetime of the instance is not directly controlled by the IoC container. /// </param> /// <param name="cosmosDataStoreConfiguration">The data store configuration</param> /// <param name="cosmosDocumentQueryFactory">The factory used to create the document query.</param> /// <param name="retryExceptionPolicyFactory">The retry exception policy factory.</param> /// <param name="fhirRequestContextAccessor">The fhir request context accessor.</param> /// <param name="namedCosmosCollectionConfigurationAccessor">The IOptions accessor to get a named version.</param> /// <param name="logger">The logger instance.</param> public FhirDataStore( IScoped <IDocumentClient> documentClient, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, FhirCosmosDocumentQueryFactory cosmosDocumentQueryFactory, RetryExceptionPolicyFactory retryExceptionPolicyFactory, IFhirRequestContextAccessor fhirRequestContextAccessor, IOptionsMonitor <CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, ILogger <FhirDataStore> logger) { EnsureArg.IsNotNull(documentClient, nameof(documentClient)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(cosmosDocumentQueryFactory, nameof(cosmosDocumentQueryFactory)); EnsureArg.IsNotNull(retryExceptionPolicyFactory, nameof(retryExceptionPolicyFactory)); EnsureArg.IsNotNull(namedCosmosCollectionConfigurationAccessor, nameof(namedCosmosCollectionConfigurationAccessor)); EnsureArg.IsNotNull(logger, nameof(logger)); _collectionConfiguration = namedCosmosCollectionConfigurationAccessor.Get(Constants.CollectionConfigurationName); _cosmosDocumentQueryFactory = cosmosDocumentQueryFactory; _retryExceptionPolicyFactory = retryExceptionPolicyFactory; _logger = logger; _documentClient = new FhirDocumentClient(documentClient.Value, fhirRequestContextAccessor, cosmosDataStoreConfiguration.ContinuationTokenSizeLimitInKb); _cosmosDataStoreConfiguration = cosmosDataStoreConfiguration; _collectionUri = cosmosDataStoreConfiguration.GetRelativeCollectionUri(_collectionConfiguration.CollectionId); _upsertWithHistoryProc = new UpsertWithHistory(); _hardDelete = new HardDelete(); }
public CosmosContainerProvider( CosmosDataStoreConfiguration cosmosDataStoreConfiguration, IOptionsMonitor <CosmosCollectionConfiguration> collectionConfiguration, ICosmosClientInitializer cosmosClientInitializer, ILogger <CosmosContainerProvider> logger, IEnumerable <ICollectionInitializer> collectionInitializers) { EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(collectionConfiguration, nameof(collectionConfiguration)); EnsureArg.IsNotNull(cosmosClientInitializer, nameof(cosmosClientInitializer)); EnsureArg.IsNotNull(logger, nameof(logger)); EnsureArg.IsNotNull(collectionInitializers, nameof(collectionInitializers)); _logger = logger; string collectionId = collectionConfiguration.Get(Constants.CollectionConfigurationName).CollectionId; _client = cosmosClientInitializer.CreateCosmosClient(cosmosDataStoreConfiguration); _initializationOperation = new RetryableInitializationOperation( () => cosmosClientInitializer.InitializeDataStore(_client, cosmosDataStoreConfiguration, collectionInitializers)); _container = new Lazy <Container>(() => cosmosClientInitializer.CreateFhirContainer( _client, cosmosDataStoreConfiguration.DatabaseId, collectionId)); }
/// <summary> /// Initializes a new instance of the <see cref="CosmosFhirDataStore"/> class. /// </summary> /// <param name="containerScope"> /// A function that returns an <see cref="Container"/>. /// Note that this is a function so that the lifetime of the instance is not directly controlled by the IoC container. /// </param> /// <param name="cosmosDataStoreConfiguration">The data store configuration.</param> /// <param name="namedCosmosCollectionConfigurationAccessor">The IOptions accessor to get a named version.</param> /// <param name="cosmosQueryFactory">The factory used to create the document query.</param> /// <param name="retryExceptionPolicyFactory">The retry exception policy factory.</param> /// <param name="logger">The logger instance.</param> /// <param name="modelInfoProvider">The model provider</param> /// <param name="coreFeatures">The core feature configuration</param> public CosmosFhirDataStore( IScoped <Container> containerScope, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, IOptionsMonitor <CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, ICosmosQueryFactory cosmosQueryFactory, RetryExceptionPolicyFactory retryExceptionPolicyFactory, ILogger <CosmosFhirDataStore> logger, IModelInfoProvider modelInfoProvider, IOptions <CoreFeatureConfiguration> coreFeatures) { EnsureArg.IsNotNull(containerScope, nameof(containerScope)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(namedCosmosCollectionConfigurationAccessor, nameof(namedCosmosCollectionConfigurationAccessor)); EnsureArg.IsNotNull(cosmosQueryFactory, nameof(cosmosQueryFactory)); EnsureArg.IsNotNull(retryExceptionPolicyFactory, nameof(retryExceptionPolicyFactory)); EnsureArg.IsNotNull(logger, nameof(logger)); EnsureArg.IsNotNull(modelInfoProvider, nameof(modelInfoProvider)); EnsureArg.IsNotNull(coreFeatures, nameof(coreFeatures)); _containerScope = containerScope; _cosmosQueryFactory = cosmosQueryFactory; _retryExceptionPolicyFactory = retryExceptionPolicyFactory; _logger = logger; _modelInfoProvider = modelInfoProvider; _coreFeatures = coreFeatures.Value; }
/// <summary> /// Initializes a new instance of the <see cref="CosmosFhirDataStore"/> class. /// </summary> /// <param name="documentClientScope"> /// A function that returns an <see cref="IDocumentClient"/>. /// Note that this is a function so that the lifetime of the instance is not directly controlled by the IoC container. /// </param> /// <param name="cosmosDataStoreConfiguration">The data store configuration.</param> /// <param name="namedCosmosCollectionConfigurationAccessor">The IOptions accessor to get a named version.</param> /// <param name="cosmosDocumentQueryFactory">The factory used to create the document query.</param> /// <param name="retryExceptionPolicyFactory">The retry exception policy factory.</param> /// <param name="logger">The logger instance.</param> /// <param name="modelInfoProvider">The model provider</param> public CosmosFhirDataStore( IScoped <IDocumentClient> documentClientScope, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, IOptionsMonitor <CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, FhirCosmosDocumentQueryFactory cosmosDocumentQueryFactory, RetryExceptionPolicyFactory retryExceptionPolicyFactory, ILogger <CosmosFhirDataStore> logger, IModelInfoProvider modelInfoProvider) { EnsureArg.IsNotNull(documentClientScope, nameof(documentClientScope)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(namedCosmosCollectionConfigurationAccessor, nameof(namedCosmosCollectionConfigurationAccessor)); EnsureArg.IsNotNull(cosmosDocumentQueryFactory, nameof(cosmosDocumentQueryFactory)); EnsureArg.IsNotNull(retryExceptionPolicyFactory, nameof(retryExceptionPolicyFactory)); EnsureArg.IsNotNull(logger, nameof(logger)); EnsureArg.IsNotNull(modelInfoProvider, nameof(modelInfoProvider)); _documentClientScope = documentClientScope; _cosmosDocumentQueryFactory = cosmosDocumentQueryFactory; _retryExceptionPolicyFactory = retryExceptionPolicyFactory; _logger = logger; _modelInfoProvider = modelInfoProvider; CosmosCollectionConfiguration collectionConfiguration = namedCosmosCollectionConfigurationAccessor.Get(Constants.CollectionConfigurationName); DatabaseId = cosmosDataStoreConfiguration.DatabaseId; CollectionId = collectionConfiguration.CollectionId; CollectionUri = cosmosDataStoreConfiguration.GetRelativeCollectionUri(collectionConfiguration.CollectionId); _upsertWithHistoryProc = new UpsertWithHistory(); _hardDelete = new HardDelete(); }
/// <inheritdoc /> public async Task InitializeDataStore(CosmosClient client, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, IEnumerable <ICollectionInitializer> collectionInitializers) { EnsureArg.IsNotNull(client, nameof(client)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(collectionInitializers, nameof(collectionInitializers)); try { _logger.LogInformation("Initializing Cosmos DB Database {DatabaseId} and collections", cosmosDataStoreConfiguration.DatabaseId); if (cosmosDataStoreConfiguration.AllowDatabaseCreation) { _logger.LogInformation("CreateDatabaseIfNotExists {DatabaseId}", cosmosDataStoreConfiguration.DatabaseId); await _retryExceptionPolicyFactory.GetRetryPolicy().ExecuteAsync( async() => await client.CreateDatabaseIfNotExistsAsync( cosmosDataStoreConfiguration.DatabaseId, cosmosDataStoreConfiguration.InitialDatabaseThroughput.HasValue ? ThroughputProperties.CreateManualThroughput(cosmosDataStoreConfiguration.InitialDatabaseThroughput.Value) : null)); } foreach (var collectionInitializer in collectionInitializers) { await collectionInitializer.InitializeCollection(client); } _logger.LogInformation("Cosmos DB Database {DatabaseId} and collections successfully initialized", cosmosDataStoreConfiguration.DatabaseId); } catch (Exception ex) { LogLevel logLevel = ex is RequestRateExceededException ? LogLevel.Warning : LogLevel.Critical; _logger.Log(logLevel, ex, "Cosmos DB Database {DatabaseId} and collections initialization failed", cosmosDataStoreConfiguration.DatabaseId); throw; } }
/// <inheritdoc /> public CosmosClient CreateCosmosClient(CosmosDataStoreConfiguration configuration) { EnsureArg.IsNotNull(configuration, nameof(configuration)); var host = configuration.Host; var key = configuration.Key; if (string.IsNullOrWhiteSpace(host) && string.IsNullOrWhiteSpace(key)) { _logger.LogWarning("No connection string provided, attempting to connect to local emulator."); host = CosmosDbLocalEmulator.Host; key = CosmosDbLocalEmulator.Key; } _logger.LogInformation("Creating CosmosClient instance for {DatabaseId}, Host: {Host}", configuration.DatabaseId, host); var builder = new CosmosClientBuilder(host, key) .WithConnectionModeDirect(enableTcpConnectionEndpointRediscovery: true) .WithCustomSerializer(new FhirCosmosSerializer()) .WithThrottlingRetryOptions(TimeSpan.FromSeconds(configuration.RetryOptions.MaxWaitTimeInSeconds), configuration.RetryOptions.MaxNumberOfRetries) .AddCustomHandlers(_requestHandlers.ToArray()); if (configuration.PreferredLocations?.Any() == true) { builder.WithApplicationPreferredRegions(configuration.PreferredLocations?.ToArray()); } if (configuration.DefaultConsistencyLevel != null) { builder.WithConsistencyLevel(configuration.DefaultConsistencyLevel.Value); } return(builder.Build()); }
public CollectionSettingsUpdater(ILogger <CollectionSettingsUpdater> logger, CosmosDataStoreConfiguration configuration) { EnsureArg.IsNotNull(logger, nameof(logger)); EnsureArg.IsNotNull(configuration, nameof(configuration)); _logger = logger; _configuration = configuration; }
public RetryExceptionPolicyFactory(CosmosDataStoreConfiguration configuration) { EnsureArg.IsNotNull(configuration, nameof(configuration)); _maxNumberOfRetries = configuration.RetryOptions.MaxNumberOfRetries; _minWaitTime = TimeSpan.FromSeconds(Math.Min(RetryStrategy.DefaultMinBackoff.TotalSeconds, configuration.RetryOptions.MaxWaitTimeInSeconds)); _maxWaitTime = TimeSpan.FromSeconds(configuration.RetryOptions.MaxWaitTimeInSeconds); }
public IntegrationTestCosmosDataStore() { _cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration { Host = Environment.GetEnvironmentVariable("CosmosDb:Host") ?? CosmosDbLocalEmulator.Host, Key = Environment.GetEnvironmentVariable("CosmosDb:Key") ?? CosmosDbLocalEmulator.Key, DatabaseId = Environment.GetEnvironmentVariable("CosmosDb:DatabaseId") ?? "FhirTests", AllowDatabaseCreation = true, PreferredLocations = Environment.GetEnvironmentVariable("CosmosDb:PreferredLocations")?.Split(';', StringSplitOptions.RemoveEmptyEntries), }; _cosmosCollectionConfiguration = new CosmosCollectionConfiguration { CollectionId = Guid.NewGuid().ToString(), }; var fhirStoredProcs = typeof(IFhirStoredProcedure).Assembly .GetTypes() .Where(x => !x.IsAbstract && typeof(IFhirStoredProcedure).IsAssignableFrom(x)) .ToArray() .Select(type => (IFhirStoredProcedure)Activator.CreateInstance(type)); var optionsMonitor = Substitute.For <IOptionsMonitor <CosmosCollectionConfiguration> >(); optionsMonitor.Get(CosmosDb.Constants.CollectionConfigurationName).Returns(_cosmosCollectionConfiguration); var updaters = new IFhirCollectionUpdater[] { new FhirCollectionSettingsUpdater(_cosmosDataStoreConfiguration, optionsMonitor, NullLogger <FhirCollectionSettingsUpdater> .Instance), new FhirStoredProcedureInstaller(fhirStoredProcs), }; var dbLock = new CosmosDbDistributedLockFactory(Substitute.For <Func <IScoped <IDocumentClient> > >(), NullLogger <CosmosDbDistributedLock> .Instance); var upgradeManager = new FhirCollectionUpgradeManager(updaters, _cosmosDataStoreConfiguration, optionsMonitor, dbLock, NullLogger <FhirCollectionUpgradeManager> .Instance); IDocumentClientTestProvider testProvider = new DocumentClientReadWriteTestProvider(); var documentClientInitializer = new DocumentClientInitializer(testProvider, NullLogger <DocumentClientInitializer> .Instance); _documentClient = documentClientInitializer.CreateDocumentClient(_cosmosDataStoreConfiguration); var fhirCollectionInitializer = new CollectionInitializer(_cosmosCollectionConfiguration.CollectionId, _cosmosDataStoreConfiguration, _cosmosCollectionConfiguration.InitialCollectionThroughput, upgradeManager, NullLogger <CollectionInitializer> .Instance); documentClientInitializer.InitializeDataStore(_documentClient, _cosmosDataStoreConfiguration, new List <ICollectionInitializer> { fhirCollectionInitializer }).GetAwaiter().GetResult(); var cosmosDocumentQueryFactory = new FhirCosmosDocumentQueryFactory(Substitute.For <IFhirRequestContextAccessor>(), NullFhirDocumentQueryLogger.Instance); var fhirRequestContextAccessor = new FhirRequestContextAccessor(); _dataStore = new FhirDataStore( new NonDisposingScope(_documentClient), _cosmosDataStoreConfiguration, cosmosDocumentQueryFactory, new RetryExceptionPolicyFactory(_cosmosDataStoreConfiguration), fhirRequestContextAccessor, optionsMonitor, NullLogger <FhirDataStore> .Instance); }
/// <inheritdoc /> public IDocumentClient CreateDocumentClient(CosmosDataStoreConfiguration configuration) { EnsureArg.IsNotNull(configuration, nameof(configuration)); _logger.LogInformation("Creating DocumentClient instance for {DatabaseUrl}", configuration.RelativeDatabaseUri); var connectionPolicy = new ConnectionPolicy { ConnectionMode = configuration.ConnectionMode, ConnectionProtocol = configuration.ConnectionProtocol, RetryOptions = new RetryOptions { MaxRetryAttemptsOnThrottledRequests = configuration.RetryOptions.MaxNumberOfRetries, MaxRetryWaitTimeInSeconds = configuration.RetryOptions.MaxWaitTimeInSeconds, }, }; if (configuration.PreferredLocations != null && configuration.PreferredLocations.Any()) { _logger.LogInformation("Setting DocumentClient PreferredLocations to {PreferredLocations}", string.Join(";", configuration.PreferredLocations)); foreach (var preferredLocation in configuration.PreferredLocations) { connectionPolicy.PreferredLocations.Add(preferredLocation); } } // Setting TypeNameHandling to any value other than 'None' will be flagged // as causing potential security issues var serializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, DateFormatHandling = DateFormatHandling.IsoDateFormat, DateParseHandling = DateParseHandling.DateTimeOffset, DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind, TypeNameHandling = TypeNameHandling.None, }; serializerSettings.Converters.Add(new StringEnumConverter()); // By default, the Json.NET serializer uses 'F' instead of 'f' for fractions. // 'F' will omit the trailing digits if they are 0. You might end up getting something like '2018-02-07T20:04:49.97114+00:00' // where the fraction is actually 971140. Because the ordering is done as string, // if the values don't always have complete 7 digits, the comparison might not work properly. serializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeFormat = "o" }); return(new FhirDocumentClient( new DocumentClient(new Uri(configuration.Host), configuration.Key, serializerSettings, connectionPolicy, configuration.DefaultConsistencyLevel), _fhirRequestContextAccessor, configuration.ContinuationTokenSizeLimitInKb, _cosmosResponseProcessor)); }
public FhirCosmosResponseHandler( Func <IScoped <Container> > client, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, IFhirRequestContextAccessor fhirRequestContextAccessor, ICosmosResponseProcessor cosmosResponseProcessor) { _client = client; _cosmosDataStoreConfiguration = cosmosDataStoreConfiguration; _fhirRequestContextAccessor = fhirRequestContextAccessor; _cosmosResponseProcessor = cosmosResponseProcessor; }
public CosmosDbSearchParameterStatusDataStore( Func <IScoped <Container> > containerScopeFactory, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, ICosmosQueryFactory queryFactory) { EnsureArg.IsNotNull(containerScopeFactory, nameof(containerScopeFactory)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(queryFactory, nameof(queryFactory)); _containerScopeFactory = containerScopeFactory; _queryFactory = queryFactory; }
public CosmosDbSearchParameterStatusInitializer( FilebasedSearchParameterStatusDataStore.Resolver filebasedSearchParameterStatusDataStoreResolver, ICosmosQueryFactory queryFactory, CosmosDataStoreConfiguration configuration) { EnsureArg.IsNotNull(filebasedSearchParameterStatusDataStoreResolver, nameof(filebasedSearchParameterStatusDataStoreResolver)); EnsureArg.IsNotNull(queryFactory, nameof(queryFactory)); _filebasedSearchParameterStatusDataStore = filebasedSearchParameterStatusDataStoreResolver.Invoke(); _queryFactory = queryFactory; _configuration = configuration; }
public FhirCollectionSettingsUpdater( CosmosDataStoreConfiguration configuration, IOptionsMonitor <CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, ILogger <FhirCollectionSettingsUpdater> logger) { EnsureArg.IsNotNull(configuration, nameof(configuration)); EnsureArg.IsNotNull(namedCosmosCollectionConfigurationAccessor, nameof(namedCosmosCollectionConfigurationAccessor)); EnsureArg.IsNotNull(logger, nameof(logger)); _configuration = configuration; _collectionConfiguration = namedCosmosCollectionConfigurationAccessor.Get(Constants.CollectionConfigurationName); _logger = logger; }
public CollectionInitializer(string collectionId, CosmosDataStoreConfiguration cosmosDataStoreConfiguration, int?initialCollectionThroughput, IUpgradeManager upgradeManager, ILogger <CollectionInitializer> logger) { EnsureArg.IsNotNull(collectionId, nameof(collectionId)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(upgradeManager, nameof(upgradeManager)); EnsureArg.IsNotNull(logger, nameof(logger)); _collectionId = collectionId; _cosmosDataStoreConfiguration = cosmosDataStoreConfiguration; _initialCollectionThroughput = initialCollectionThroughput; _upgradeManager = upgradeManager; _logger = logger; }
/// <summary> /// Ensures that the necessary database and collection exist with the proper indexing policy and stored procedures /// </summary> /// <param name="documentClient">The <see cref="DocumentClient"/> instance to use for initialization.</param> /// <param name="cosmosDataStoreConfiguration">The data store configuration.</param> /// <returns>A task</returns> public async Task InitializeDataStore(IDocumentClient documentClient, CosmosDataStoreConfiguration cosmosDataStoreConfiguration) { EnsureArg.IsNotNull(documentClient, nameof(documentClient)); EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); try { _logger.LogInformation("Initializing Cosmos DB collection {CollectionUri}", cosmosDataStoreConfiguration.AbsoluteCollectionUri); if (cosmosDataStoreConfiguration.AllowDatabaseCreation) { _logger.LogDebug("CreateDatabaseIfNotExists {DatabaseId})", cosmosDataStoreConfiguration.DatabaseId); await documentClient.CreateDatabaseIfNotExistsAsync(new Database { Id = cosmosDataStoreConfiguration.DatabaseId, }); } _logger.LogDebug("CreateDocumentCollectionIfNotExists {HostDescription}", cosmosDataStoreConfiguration.AbsoluteCollectionUri); DocumentCollection existingDocumentCollection = await documentClient.TryGetDocumentCollectionAsync(cosmosDataStoreConfiguration.RelativeCollectionUri); if (existingDocumentCollection == null) { var documentCollection = new DocumentCollection { Id = cosmosDataStoreConfiguration.CollectionId, PartitionKey = new PartitionKeyDefinition { Paths = { $"/{KnownResourceWrapperProperties.PartitionKey}", }, }, }; existingDocumentCollection = await documentClient.CreateDocumentCollectionIfNotExistsAsync( cosmosDataStoreConfiguration.RelativeDatabaseUri, cosmosDataStoreConfiguration.RelativeCollectionUri, documentCollection); } await _upgradeManager.SetupCollectionAsync(documentClient, existingDocumentCollection); _logger.LogInformation("Cosmos DB collection {CollectionUri} successfully initialized", cosmosDataStoreConfiguration.AbsoluteCollectionUri); } catch (Exception ex) { _logger.LogCritical(ex, "Cosmos DB collection {CollectionUri} initialization failed", cosmosDataStoreConfiguration.AbsoluteCollectionUri); throw; } }
public RetryExceptionPolicyFactory(CosmosDataStoreConfiguration configuration, RequestContextAccessor <IFhirRequestContext> requestContextAccessor) { _requestContextAccessor = requestContextAccessor; EnsureArg.IsNotNull(configuration, nameof(configuration)); EnsureArg.IsNotNull(requestContextAccessor, nameof(requestContextAccessor)); _sdkOnlyRetryPolicy = Policy.NoOpAsync(); _bundleActionRetryPolicy = configuration.IndividualBatchActionRetryOptions.MaxNumberOfRetries > 0 ? CreateExtendedRetryPolicy(configuration.IndividualBatchActionRetryOptions.MaxNumberOfRetries / configuration.RetryOptions.MaxNumberOfRetries, configuration.IndividualBatchActionRetryOptions.MaxWaitTimeInSeconds) : Policy.NoOpAsync(); _backgroundJobRetryPolicy = CreateExtendedRetryPolicy(100, -1); }
public TestCosmosHealthCheck( IScoped <Container> container, CosmosDataStoreConfiguration configuration, IOptionsSnapshot <CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, ICosmosClientTestProvider testProvider, ILogger <CosmosHealthCheck> logger) : base( container, configuration, namedCosmosCollectionConfigurationAccessor, testProvider, logger) { }
public DocumentClientProvider( CosmosDataStoreConfiguration cosmosDataStoreConfiguration, IDocumentClientInitializer documentClientInitializer, ILogger <DocumentClientProvider> logger) { EnsureArg.IsNotNull(cosmosDataStoreConfiguration, nameof(cosmosDataStoreConfiguration)); EnsureArg.IsNotNull(documentClientInitializer, nameof(documentClientInitializer)); EnsureArg.IsNotNull(logger, nameof(logger)); _documentClient = documentClientInitializer.CreateDocumentClient(cosmosDataStoreConfiguration); _initializationOperation = new RetryableInitializationOperation( () => documentClientInitializer.InitializeDataStore(_documentClient, cosmosDataStoreConfiguration)); }
public FhirCollectionUpgradeManager( IEnumerable <IFhirCollectionUpdater> collectionUpdater, CosmosDataStoreConfiguration configuration, IOptionsMonitor <CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, ICosmosDbDistributedLockFactory lockFactory, ILogger <FhirCollectionUpgradeManager> logger) : base( collectionUpdater, configuration, GetCosmosCollectionConfiguration(namedCosmosCollectionConfigurationAccessor, Constants.CollectionConfigurationName), lockFactory, logger) { }
public ControlPlaneDataStoreTests() { var scopedIDocumentClient = Substitute.For <IScoped <IDocumentClient> >(); var documentClient = Substitute.For <IDocumentClient>(); scopedIDocumentClient.Value.Returns(documentClient); var cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration { AllowDatabaseCreation = false, ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Https, DatabaseId = "testdatabaseid", Host = "https://fakehost", Key = "ZmFrZWtleQ==", // "fakekey" PreferredLocations = null, }; var cosmosDocumentQueryFactory = Substitute.For <ICosmosDocumentQueryFactory>(); var identityProviderDocumentQuery = Substitute.For <IDocumentQuery <CosmosIdentityProvider> >(); _cosmosIdentityProvider = Substitute.For <CosmosIdentityProvider>(); _cosmosIdentityProvider.ETag.Returns("\"1\""); _cosmosIdentityProvider.Name.Returns("aad"); _cosmosIdentityProvider.Audience.Returns(new[] { "fhir-api" }); _cosmosIdentityProvider.Authority.Returns("https://login.microsoftonline.com/common"); var feedResponse = new FeedResponse <dynamic>(new List <dynamic> { _cosmosIdentityProvider }); identityProviderDocumentQuery.ExecuteNextAsync(Arg.Any <CancellationToken>()).Returns(feedResponse); cosmosDocumentQueryFactory.Create <CosmosIdentityProvider>(Arg.Any <IDocumentClient>(), Arg.Any <CosmosQueryContext>()).Returns(identityProviderDocumentQuery); var optionsMonitor = Substitute.For <IOptionsMonitor <CosmosCollectionConfiguration> >(); optionsMonitor.Get(Constants.CollectionConfigurationName).Returns(new CosmosCollectionConfiguration { CollectionId = "collectionId" }); var logger = NullLogger <ControlPlaneDataStore> .Instance; _controlPlaneDataStore = new ControlPlaneDataStore( scopedIDocumentClient, cosmosDataStoreConfiguration, cosmosDocumentQueryFactory, optionsMonitor, logger); }
public TestCosmosHealthCheck( IScoped <IDocumentClient> documentClient, CosmosDataStoreConfiguration configuration, IOptionsSnapshot <CosmosCollectionConfiguration> namedCosmosCollectionConfigurationAccessor, IDocumentClientTestProvider testProvider, ILogger <CosmosHealthCheck> logger) : base( documentClient, configuration, namedCosmosCollectionConfigurationAccessor, TestCosmosHealthCheckName, testProvider, logger) { }
public FhirCosmosClientInitializerTests() { var clientTestProvider = Substitute.For <ICosmosClientTestProvider>(); _cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration(); _initializer = new FhirCosmosClientInitializer( clientTestProvider, Enumerable.Empty <RequestHandler>(), NullLogger <FhirCosmosClientInitializer> .Instance); _collectionInitializers = new List <ICollectionInitializer> { _collectionInitializer1, _collectionInitializer2 }; }
public async Task PerformTest(Container container, CosmosDataStoreConfiguration configuration, CosmosCollectionConfiguration cosmosCollectionConfiguration) { var requestOptions = new ItemRequestOptions { ConsistencyLevel = ConsistencyLevel.Session }; var resourceResponse = await container.UpsertItemAsync( _document, _partitionKey, requestOptions); requestOptions.SessionToken = resourceResponse.Headers.Session; await container.ReadItemAsync <HealthCheckDocument>(resourceResponse.Resource.Id, _partitionKey, requestOptions); }
public async Task PerformTest(IDocumentClient documentClient, CosmosDataStoreConfiguration configuration, CosmosCollectionConfiguration cosmosCollectionConfiguration) { var requestOptions = new RequestOptions { ConsistencyLevel = ConsistencyLevel.Session, PartitionKey = _partitionKey }; ResourceResponse <Document> resourceResponse = await documentClient.UpsertDocumentAsync( configuration.GetRelativeCollectionUri(cosmosCollectionConfiguration.CollectionId), _document, requestOptions); requestOptions.SessionToken = resourceResponse.SessionToken; await documentClient.ReadDocumentAsync(resourceResponse.Resource.SelfLink, requestOptions); }
public DocumentClientInitializerTests() { _cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration { AllowDatabaseCreation = false, ConnectionMode = Azure.Documents.Client.ConnectionMode.Direct, ConnectionProtocol = Azure.Documents.Client.Protocol.Https, DatabaseId = "testdatabaseid", Host = "https://fakehost", Key = "ZmFrZWtleQ==", // "fakekey" PreferredLocations = null, }; _cosmosDataStoreConfiguration.RetryOptions.MaxNumberOfRetries = 10; _cosmosDataStoreConfiguration.RetryOptions.MaxWaitTimeInSeconds = 99; }
public FhirCosmosClientInitializerTests() { var clientTestProvider = Substitute.For <ICosmosClientTestProvider>(); _cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration(); _initializer = new FhirCosmosClientInitializer( clientTestProvider, () => new[] { new TestRequestHandler() }, new RetryExceptionPolicyFactory(_cosmosDataStoreConfiguration, Substitute.For <IFhirRequestContextAccessor>()), NullLogger <FhirCosmosClientInitializer> .Instance); _collectionInitializers = new List <ICollectionInitializer> { _collectionInitializer1, _collectionInitializer2 }; }
public CosmosDbFhirStorageTestsFixture() { _cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration { Host = Environment.GetEnvironmentVariable("CosmosDb:Host") ?? CosmosDbLocalEmulator.Host, Key = Environment.GetEnvironmentVariable("CosmosDb:Key") ?? CosmosDbLocalEmulator.Key, DatabaseId = Environment.GetEnvironmentVariable("CosmosDb:DatabaseId") ?? "FhirTests", AllowDatabaseCreation = true, PreferredLocations = Environment.GetEnvironmentVariable("CosmosDb:PreferredLocations")?.Split(';', StringSplitOptions.RemoveEmptyEntries), }; _cosmosCollectionConfiguration = new CosmosCollectionConfiguration { CollectionId = Guid.NewGuid().ToString(), }; }