Example #1
0
        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);
        }
Example #2
0
        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");
        }
Example #3
0
        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);
        }
Example #5
0
        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);
        }