public async Task <Entity> GetEntityAsync(string pk, string rk) { // Define a unique key for this method and its parameters. var key = $"Entity:{pk}_{rk}"; var cache = Connection.GetDatabase(); // Try to get the entity from the cache. var json = await cache.StringGetAsync(key); var entityFromCache = string.IsNullOrWhiteSpace(json) ? default(Entity) : JsonConvert.DeserializeObject <Entity>(json); if (entityFromCache == null) // Cache miss { // If there's a cache miss, get the entity from the original store and cache it. // Code has been omitted because it's data store dependent. Console.WriteLine("Cache miss"); var tableClient = TableStorageAccount.CreateCloudTableClient(); var table = tableClient.GetTableReference("Entities"); await table.CreateIfNotExistsAsync(); var retrieveOperation = TableOperation.Retrieve <Entity>(pk, rk); var result = await table.ExecuteAsync(retrieveOperation); var entityFromTable = (Entity)result.Result; // Avoid caching a null value. if (entityFromTable != null) { // Put the item in the cache with a custom expiration time that // depends on how critical it is to have stale data. await cache.StringSetAsync(key, entityFromTable.ToString()); await cache.KeyExpireAsync(key, TimeSpan.FromSeconds(CacheExpirationTimeInSeconds)); Console.WriteLine("Cached new entity"); } else { Console.WriteLine("Entity not found in backend - not caching null"); } return(entityFromTable); } else { Console.WriteLine("Found in cache"); } return(entityFromCache); }
public async Task InsertOrUpdateEntityAsync(Entity entity) { // Update the object in the original data store. var tableClient = TableStorageAccount.CreateCloudTableClient(); var table = tableClient.GetTableReference("Entities"); await table.CreateIfNotExistsAsync(); var insertOrReplaceOperation = TableOperation.InsertOrReplace(entity); await table.ExecuteAsync(insertOrReplaceOperation); // Invalidate the current cache object. var cache = Connection.GetDatabase(); var key = $"Entity:{entity.PartitionKey}_{entity.RowKey}"; await cache.KeyDeleteAsync(key); // Delete this key from the cache. Console.WriteLine("Updated backend and deleted key from cache"); }
public static IServiceCollection AddTableStorageService(this IServiceCollection services) { services.AddSingleton(provider => { var options = provider.GetRequiredService <IOptions <DatabaseOptions> >().Value; return(TableStorageAccount.Parse(options.ConnectionString)); }); services.AddTransient(provider => { var account = provider.GetRequiredService <TableStorageAccount>(); return(account.CreateCloudTableClient()); }); services.AddTransient <TablePackageService>(); return(services); }
public static BaGetApplication AddAzureTableDatabase(this BaGetApplication app) { app.Services.AddBaGetOptions <AzureTableOptions>(nameof(BaGetOptions.Database)); app.Services.AddTransient <TablePackageDatabase>(); app.Services.AddTransient <TableOperationBuilder>(); app.Services.AddTransient <TableSearchService>(); app.Services.TryAddTransient <IPackageDatabase>(provider => provider.GetRequiredService <TablePackageDatabase>()); app.Services.TryAddTransient <ISearchService>(provider => provider.GetRequiredService <TableSearchService>()); app.Services.TryAddTransient <ISearchIndexer>(provider => provider.GetRequiredService <NullSearchIndexer>()); app.Services.AddSingleton(provider => { var options = provider.GetRequiredService <IOptions <AzureTableOptions> >().Value; return(TableStorageAccount.Parse(options.ConnectionString)); }); app.Services.AddTransient(provider => { var account = provider.GetRequiredService <TableStorageAccount>(); return(account.CreateCloudTableClient()); }); app.Services.AddProvider <IPackageDatabase>((provider, config) => { if (!config.HasDatabaseType("AzureTable")) { return(null); } return(provider.GetRequiredService <TablePackageDatabase>()); }); app.Services.AddProvider <ISearchService>((provider, config) => { if (!config.HasSearchType("Database")) { return(null); } if (!config.HasDatabaseType("AzureTable")) { return(null); } return(provider.GetRequiredService <TableSearchService>()); }); app.Services.AddProvider <ISearchIndexer>((provider, config) => { if (!config.HasSearchType("Database")) { return(null); } if (!config.HasDatabaseType("AzureTable")) { return(null); } return(provider.GetRequiredService <NullSearchIndexer>()); }); return(app); }
public static IServiceCollection AddBaGet(this IServiceCollection services) { services.AddSingleton(provider => { return(new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, })); }); services.AddSingleton(provider => { return(new NuGetClientFactory( provider.GetRequiredService <HttpClient>(), "https://api.nuget.org/v3/index.json")); }); services.AddSingleton(provider => { var config = provider.GetRequiredService <IOptions <Configuration> >(); return(TableStorageAccount .Parse(config.Value.TableStorage.ConnectionString) .CreateCloudTableClient()); }); services.AddSingleton <IQueueClient>(provider => { var config = provider.GetRequiredService <IOptions <Configuration> >(); var builder = new ServiceBusConnectionStringBuilder( config.Value.ServiceBus.ConnectionString); return(new QueueClient(builder, ReceiveMode.PeekLock)); }); services.AddSingleton(provider => { var config = provider.GetRequiredService <IOptions <Configuration> >(); var blobClient = CloudStorageAccount .Parse(config.Value.BlobStorage.ConnectionString) .CreateCloudBlobClient(); return(blobClient.GetContainerReference(config.Value.BlobStorage.ContainerName)); }); services.AddSingleton <ISearchIndexClient>(provider => { var config = provider.GetRequiredService <IOptions <Configuration> >(); return(new SearchIndexClient( config.Value.Search.ServiceName, config.Value.Search.IndexName, new SearchCredentials(config.Value.Search.ApiKey))); }); // TODO: Move BaGet to ISearchServiceClient and remove this line: services.AddSingleton <ISearchServiceClient>(p => p.GetRequiredService <SearchServiceClient>()); services.AddSingleton(provider => { var config = provider.GetRequiredService <IOptions <Configuration> >(); return(new SearchServiceClient( config.Value.Search.ServiceName, new SearchCredentials(config.Value.Search.ApiKey))); }); services.AddSingleton <IPackageService, TablePackageService>(); services.AddSingleton <ICursor, BlobCursor>(); services.AddSingleton <IUrlGenerator, UrlGenerator>(); services.AddSingleton <IPackageDownloadsSource, PackageDownloadsJsonSource>(); services.AddSingleton <ProcessCatalogLeafItem>(); services.AddSingleton <QueueCatalogLeafItems>(); services.AddSingleton <BatchQueueClient>(); services.AddSingleton <PackageIndexer>(); services.AddSingleton <AzureSearchBatchIndexer>(); services.AddSingleton <IndexActionBuilder>(); return(services); }