diff --git a/src/Covid19Api.Controllers/Covid19Api.Controllers.csproj b/src/Covid19Api.Controllers/Covid19Api.Controllers.csproj index 9a9473e..64c985f 100644 --- a/src/Covid19Api.Controllers/Covid19Api.Controllers.csproj +++ b/src/Covid19Api.Controllers/Covid19Api.Controllers.csproj @@ -10,8 +10,6 @@ - - diff --git a/src/Covid19Api.Controllers/V1/CountryStatisticsController.cs b/src/Covid19Api.Controllers/V1/CountryStatisticsController.cs index fe9be7b..a63faf6 100644 --- a/src/Covid19Api.Controllers/V1/CountryStatisticsController.cs +++ b/src/Covid19Api.Controllers/V1/CountryStatisticsController.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Covid19Api.Presentation.Response; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatistics; using MediatR; using Microsoft.AspNetCore.Mvc; @@ -33,6 +33,6 @@ public Task LoadLatestForCountryAsync(string country) => [HttpGet("{country}/history")] public Task> LoadHistoryForCountryAsync(string country) => - this.mediator.Send(new LoadHistoricalStatisticsForCountryQuery(country)); + this.mediator.Send(new LoadHistoricalCountryStatisticsForCountryQuery(country)); } } \ No newline at end of file diff --git a/src/Covid19Api.Controllers/V1/CountryStatisticsCountryAggregatesController.cs b/src/Covid19Api.Controllers/V1/CountryStatisticsCountryAggregatesController.cs new file mode 100644 index 0000000..6bee008 --- /dev/null +++ b/src/Covid19Api.Controllers/V1/CountryStatisticsCountryAggregatesController.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Covid19Api.Presentation.Response; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatisticsAggregates; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace Covid19Api.Controllers.V1 +{ + [ApiController] + [Route("api/v1/countries/{country}/aggregates")] + public class CountryStatisticsCountryAggregatesController : ControllerBase + { + [HttpGet("{year:int}")] + public Task> LoadAggregatesForCountryInYearAsync( + [FromServices] IMediator mediator, string country, int year) + { + var query = new LoadCountryStatisticsAggregatesForCountryInYearQuery(country, year); + return mediator.Send(query); + } + } +} \ No newline at end of file diff --git a/src/Covid19Api.Controllers/V1/GlobalStatisticsAggregatesController.cs b/src/Covid19Api.Controllers/V1/GlobalStatisticsAggregatesController.cs new file mode 100644 index 0000000..6a2e21b --- /dev/null +++ b/src/Covid19Api.Controllers/V1/GlobalStatisticsAggregatesController.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Covid19Api.Presentation.Response; +using Covid19Api.UseCases.Abstractions.Queries.GlobalStatisticsAggregates; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace Covid19Api.Controllers.V1 +{ + [ApiController] + [Route("api/v1/global/aggregates")] + public class GlobalStatisticsAggregatesController + { + [HttpGet("{year:int}")] + public Task> LoadForYearAsync([FromServices] IMediator mediator, + int year) + { + var query = new LoadGlobalStatisticsAggregatesForYearQuery(year); + return mediator.Send(query); + } + } +} \ No newline at end of file diff --git a/src/Covid19Api.Controllers/V1/GlobalStatisticsController.cs b/src/Covid19Api.Controllers/V1/GlobalStatisticsController.cs index c0b852e..21ad295 100644 --- a/src/Covid19Api.Controllers/V1/GlobalStatisticsController.cs +++ b/src/Covid19Api.Controllers/V1/GlobalStatisticsController.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Covid19Api.Presentation.Response; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.GlobalStatistics; using MediatR; using Microsoft.AspNetCore.Mvc; diff --git a/src/Covid19Api.IoC/Extensions/ContainerBuilderExtensions.cs b/src/Covid19Api.IoC/Extensions/ContainerBuilderExtensions.cs index 18d9f39..ae7fc3b 100644 --- a/src/Covid19Api.IoC/Extensions/ContainerBuilderExtensions.cs +++ b/src/Covid19Api.IoC/Extensions/ContainerBuilderExtensions.cs @@ -85,7 +85,7 @@ public static ContainerBuilder RegisterWorker(this ContainerBuilder builder) builder.RegisterType() .As() .InstancePerDependency(); - + builder.RegisterType() .As() .InstancePerDependency(); diff --git a/src/Covid19Api.Mongo.Migrator/Abstractions/DatabaseMigration.cs b/src/Covid19Api.Mongo.Migrator/Abstractions/DatabaseMigration.cs index b20f528..7053e77 100644 --- a/src/Covid19Api.Mongo.Migrator/Abstractions/DatabaseMigration.cs +++ b/src/Covid19Api.Mongo.Migrator/Abstractions/DatabaseMigration.cs @@ -11,10 +11,11 @@ protected DatabaseMigration(ILogger logger) { this.logger = logger; } + public abstract int Number { get; } - + protected abstract string Name { get; } - + public async Task ExecuteUpdateAsync() { this.logger.LogInformation("Executing migration {number}-{migration}", this.Number, this.Name); diff --git a/src/Covid19Api.Mongo.Migrator/Migrations/000000_GlobalAggregatesMigration.cs b/src/Covid19Api.Mongo.Migrator/Migrations/000000_GlobalAggregatesMigration.cs index 773badf..97a671a 100644 --- a/src/Covid19Api.Mongo.Migrator/Migrations/000000_GlobalAggregatesMigration.cs +++ b/src/Covid19Api.Mongo.Migrator/Migrations/000000_GlobalAggregatesMigration.cs @@ -3,7 +3,7 @@ using Covid19Api.Mongo.Migrator.Abstractions; using Covid19Api.Mongo.Migrator.Configuration; using Covid19Api.UseCases.Abstractions.Commands; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.GlobalStatisticsAggregates; using MediatR; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -23,7 +23,7 @@ public GlobalAggregatesMigration(ILogger logger, this.mediator = mediator; this.options = options?.Value ?? throw new ArgumentNullException(nameof(options)); } - + public override int Number => 0; protected override string Name => nameof(GlobalAggregatesMigration); @@ -36,16 +36,16 @@ protected override async Task ExecuteAsync() { if (next.Month > end.Month && next.Year >= end.Year) break; - + var query = new LoadGlobalStatisticsAggregate(next.Month, next.Year); var aggregate = await this.mediator.Send(query); - + if (aggregate is {}) { next = next.AddMonths(1); continue; } - + var command = new AggregateGlobalStatisticsCommand(next.Month, next.Year); await this.mediator.Send(command); diff --git a/src/Covid19Api.Mongo.Migrator/Migrations/000001_CountryAggregatesMigration.cs b/src/Covid19Api.Mongo.Migrator/Migrations/000001_CountryAggregatesMigration.cs index 39145ea..efa2a3b 100644 --- a/src/Covid19Api.Mongo.Migrator/Migrations/000001_CountryAggregatesMigration.cs +++ b/src/Covid19Api.Mongo.Migrator/Migrations/000001_CountryAggregatesMigration.cs @@ -4,7 +4,8 @@ using Covid19Api.Mongo.Migrator.Abstractions; using Covid19Api.Mongo.Migrator.Configuration; using Covid19Api.UseCases.Abstractions.Commands; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatistics; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatisticsAggregates; using MediatR; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -24,7 +25,7 @@ public CountryAggregatesMigration(ILogger logger, this.mediator = mediator; this.options = options?.Value ?? throw new ArgumentNullException(nameof(options)); } - + public override int Number => 1; protected override string Name => nameof(CountryAggregatesMigration); @@ -37,7 +38,7 @@ protected override async Task ExecuteAsync() { if (next.Month > end.Month && next.Year >= end.Year) break; - + var loadCountriesStatisticsQuery = new LoadLatestCountriesStatisticsQuery(); var countries = (await this.mediator.Send(loadCountriesStatisticsQuery)) .Select(country => country.Country).ToList(); @@ -59,7 +60,7 @@ protected override async Task ExecuteAsync() await Task.Delay(100); continue; } - + var command = new AggregateCountryStatisticsCommand(countries.ToArray(), next.Month, next.Year); await this.mediator.Send(command); diff --git a/src/Covid19Api.Mongo.Scaffolder/Updates/000003_CountryStatisticAggregateUpdateDefinition.cs b/src/Covid19Api.Mongo.Scaffolder/Updates/000003_CountryStatisticAggregateUpdateDefinition.cs index 19d7d40..6a29089 100644 --- a/src/Covid19Api.Mongo.Scaffolder/Updates/000003_CountryStatisticAggregateUpdateDefinition.cs +++ b/src/Covid19Api.Mongo.Scaffolder/Updates/000003_CountryStatisticAggregateUpdateDefinition.cs @@ -25,19 +25,20 @@ protected override async Task ExecuteAsync() { await this.databaseContext.Database.CreateCollectionIfNotExistsAsync(CollectionNames .CountryStatisticsAggregates); - + var collection = this.databaseContext.Database.GetCollection(CollectionNames .CountryStatisticsAggregates); - + var countryIndex = Builders .IndexKeys .Ascending(statistics => statistics.Country); - var countryIndexModel = new CreateIndexModel(countryIndex, new CreateIndexOptions - { - Name = $"{CollectionNames.CountryStatisticsAggregates}_country" - }); + var countryIndexModel = new CreateIndexModel(countryIndex, + new CreateIndexOptions + { + Name = $"{CollectionNames.CountryStatisticsAggregates}_country" + }); await collection.Indexes.CreateOneAsync(countryIndexModel); @@ -49,7 +50,7 @@ await this.databaseContext.Database.CreateCollectionIfNotExistsAsync(CollectionN { Name = $"{CollectionNames.CountryStatisticsAggregates}_month_descending" }); - + await collection.Indexes.CreateOneAsync(monthIndexModel); var yearIndex = Builders @@ -60,7 +61,7 @@ await this.databaseContext.Database.CreateCollectionIfNotExistsAsync(CollectionN { Name = $"{CollectionNames.CountryStatisticsAggregates}_year_descending" }); - + await collection.Indexes.CreateOneAsync(yearIndexModel); var yearMonthIndex = Builders @@ -72,9 +73,9 @@ await this.databaseContext.Database.CreateCollectionIfNotExistsAsync(CollectionN { Name = $"{CollectionNames.CountryStatisticsAggregates}_year_month", }); - + await collection.Indexes.CreateOneAsync(yearMonthIndexModel); - + var countryYearMonthIndex = Builders .IndexKeys .Combine(countryIndex, yearIndex, monthIndex); diff --git a/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsAggregatesRepository.cs b/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsAggregatesRepository.cs index 68dd8cb..a3102f6 100644 --- a/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsAggregatesRepository.cs +++ b/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsAggregatesRepository.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading.Tasks; using Covid19Api.Domain; @@ -8,5 +9,7 @@ public interface ICountryStatisticsAggregatesRepository Task StoreAsync(CountryStatisticsAggregate countryStatisticsAggregate); Task FindAsync(string country, int month, int year); + + Task> FindForCountryInYearAsync(string country, int year); } } \ No newline at end of file diff --git a/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsRepository.cs b/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsRepository.cs index f3b44f9..2bc8280 100644 --- a/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsRepository.cs +++ b/src/Covid19Api.Repositories.Abstractions/ICountryStatisticsRepository.cs @@ -14,6 +14,7 @@ public interface ICountryStatisticsRepository Task FindInRangeAsync(string country, DateTime inclusiveStart, DateTime exclusiveEnd); + Task StoreManyAsync(IEnumerable countryStats); } } \ No newline at end of file diff --git a/src/Covid19Api.Repositories.Abstractions/IGlobalStatisticsAggregatesRepository.cs b/src/Covid19Api.Repositories.Abstractions/IGlobalStatisticsAggregatesRepository.cs index 0b15d9a..775a4af 100644 --- a/src/Covid19Api.Repositories.Abstractions/IGlobalStatisticsAggregatesRepository.cs +++ b/src/Covid19Api.Repositories.Abstractions/IGlobalStatisticsAggregatesRepository.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading.Tasks; using Covid19Api.Domain; @@ -8,5 +9,7 @@ public interface IGlobalStatisticsAggregatesRepository Task StoreAsync(GlobalStatisticsAggregate globalStatisticsAggregate); Task FindAsync(int month, int year); + + Task> FindInYearAsync(int year); } } \ No newline at end of file diff --git a/src/Covid19Api.Repositories/CountryStatisticsAggregatesRepository.cs b/src/Covid19Api.Repositories/CountryStatisticsAggregatesRepository.cs index ec6803e..b749e83 100644 --- a/src/Covid19Api.Repositories/CountryStatisticsAggregatesRepository.cs +++ b/src/Covid19Api.Repositories/CountryStatisticsAggregatesRepository.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading.Tasks; using Covid19Api.Domain; using Covid19Api.Mongo; @@ -48,6 +49,25 @@ public Task StoreAsync(CountryStatisticsAggregate countryStatisticsAggregate) return await cursor.SingleOrDefaultAsync(); } + public async Task> FindForCountryInYearAsync(string country, int year) + { + // ReSharper disable once SpecifyStringComparison + var countryFilter = + Builders.Filter.Where(statistics => + statistics.Country.ToLower() == country.ToLower()); + + var yearFilter = + Builders.Filter.Where(statistics => statistics.Year == year); + + var filter = countryFilter & yearFilter; + + var collection = this.GetCollection(); + + var cursor = await collection.FindAsync(filter); + + return await cursor.ToListAsync(); + } + private IMongoCollection GetCollection() => this.context.Database.GetCollection(CollectionNames .CountryStatisticsAggregates); diff --git a/src/Covid19Api.Repositories/GlobalStatisticsAggregatesRepository.cs b/src/Covid19Api.Repositories/GlobalStatisticsAggregatesRepository.cs index 5392caf..2c48744 100644 --- a/src/Covid19Api.Repositories/GlobalStatisticsAggregatesRepository.cs +++ b/src/Covid19Api.Repositories/GlobalStatisticsAggregatesRepository.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading.Tasks; using Covid19Api.Domain; using Covid19Api.Mongo; @@ -38,6 +39,15 @@ public Task StoreAsync(GlobalStatisticsAggregate globalStatisticsAggregate) return await cursor.SingleOrDefaultAsync(); } + public async Task> FindInYearAsync(int year) + { + var collection = this.GetCollection(); + + var cursor = await collection.FindAsync(aggregate => aggregate.Year == year); + + return await cursor.ToListAsync(); + } + private IMongoCollection GetCollection() => this.context.Database.GetCollection(CollectionNames .GlobalStatisticsAggregates); diff --git a/src/Covid19Api.Services/Decorator/CountryMetaDataLoaderDecorator.cs b/src/Covid19Api.Services/Decorator/CountryMetaDataLoaderDecorator.cs index 49865af..6b390dd 100644 --- a/src/Covid19Api.Services/Decorator/CountryMetaDataLoaderDecorator.cs +++ b/src/Covid19Api.Services/Decorator/CountryMetaDataLoaderDecorator.cs @@ -28,8 +28,8 @@ public CountryMetaDataLoaderDecorator(IDistributedCache distributedCache, this.countryMetaDataLoader = countryMetaDataLoader; this.compressionService = compressionService; } - - + + public void Dispose() { Mutex.Dispose(); diff --git a/src/Covid19Api.Services/Loader/CountryMetaDataLoader.cs b/src/Covid19Api.Services/Loader/CountryMetaDataLoader.cs index 0febec4..97f2f89 100644 --- a/src/Covid19Api.Services/Loader/CountryMetaDataLoader.cs +++ b/src/Covid19Api.Services/Loader/CountryMetaDataLoader.cs @@ -18,7 +18,7 @@ public class CountryMetaDataLoader : ICountryMetaDataLoader { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - + private readonly ILogger logger; private readonly IHttpClientFactory httpClientFactory; @@ -38,7 +38,7 @@ public async Task LoadCountryMetaDataAsync() { var deserialized = await JsonSerializer.DeserializeAsync( await response.Content.ReadAsStreamAsync(), SerializerOptions); - + return deserialized ?? Array.Empty(); } diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalCountriesStatisticsQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadHistoricalCountriesStatisticsQuery.cs similarity index 90% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalCountriesStatisticsQuery.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadHistoricalCountriesStatisticsQuery.cs index 341e97b..5d8c27f 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalCountriesStatisticsQuery.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadHistoricalCountriesStatisticsQuery.cs @@ -5,7 +5,7 @@ using Covid19Api.UseCases.Abstractions.Models; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.CountryStatistics { public class LoadHistoricalCountriesStatisticsQuery : ICacheableRequest, IRequest> { diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalStatisticsForCountryQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadHistoricalCountryStatisticsForCountryQuery.cs similarity index 57% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalStatisticsForCountryQuery.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadHistoricalCountryStatisticsForCountryQuery.cs index 4566956..3480d7e 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalStatisticsForCountryQuery.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadHistoricalCountryStatisticsForCountryQuery.cs @@ -5,12 +5,12 @@ using Covid19Api.UseCases.Abstractions.Models; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.CountryStatistics { - public class LoadHistoricalStatisticsForCountryQuery : ICacheableRequest, + public class LoadHistoricalCountryStatisticsForCountryQuery : ICacheableRequest, IRequest> { - public LoadHistoricalStatisticsForCountryQuery(string country) + public LoadHistoricalCountryStatisticsForCountryQuery(string country) { this.Country = country; } @@ -18,7 +18,7 @@ public LoadHistoricalStatisticsForCountryQuery(string country) public string Country { get; } public CacheConfiguration GetCacheConfiguration() => - new CacheConfiguration($"{nameof(LoadHistoricalStatisticsForCountryQuery)}_{Country}", + new CacheConfiguration($"{nameof(LoadHistoricalCountryStatisticsForCountryQuery)}_{this.Country}", TimeSpan.FromMinutes(30)); } } \ No newline at end of file diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestCountriesStatisticsQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadLatestCountriesStatisticsQuery.cs similarity index 87% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestCountriesStatisticsQuery.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadLatestCountriesStatisticsQuery.cs index 0ecac4b..2aba8db 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestCountriesStatisticsQuery.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadLatestCountriesStatisticsQuery.cs @@ -5,7 +5,7 @@ using Covid19Api.UseCases.Abstractions.Models; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.CountryStatistics { public class LoadLatestCountriesStatisticsQuery : ICacheableRequest, IRequest> { diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestStatisticsForCountryQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadLatestStatisticsForCountryQuery.cs similarity index 85% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestStatisticsForCountryQuery.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadLatestStatisticsForCountryQuery.cs index 7cc4853..ccca360 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestStatisticsForCountryQuery.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatistics/LoadLatestStatisticsForCountryQuery.cs @@ -4,7 +4,7 @@ using Covid19Api.UseCases.Abstractions.Models; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.CountryStatistics { public class LoadLatestStatisticsForCountryQuery : ICacheableRequest, IRequest { @@ -16,7 +16,7 @@ public LoadLatestStatisticsForCountryQuery(string country) public string Country { get; } public CacheConfiguration GetCacheConfiguration() => - new CacheConfiguration($"{nameof(LoadLatestStatisticsForCountryQuery)}_{Country}", + new CacheConfiguration($"{nameof(LoadLatestStatisticsForCountryQuery)}_{this.Country}", TimeSpan.FromMinutes(30)); } } \ No newline at end of file diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadCountryStatisticsAggregate.cs b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregate.cs similarity index 85% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadCountryStatisticsAggregate.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregate.cs index 7df342a..039dd02 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadCountryStatisticsAggregate.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregate.cs @@ -1,7 +1,7 @@ using Covid19Api.Presentation.Response; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.CountryStatisticsAggregates { public class LoadCountryStatisticsAggregate : IRequest { diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregatesForCountryInYearQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregatesForCountryInYearQuery.cs new file mode 100644 index 0000000..b766a4c --- /dev/null +++ b/src/Covid19Api.UseCases.Abstractions/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregatesForCountryInYearQuery.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using Covid19Api.Presentation.Response; +using MediatR; + +namespace Covid19Api.UseCases.Abstractions.Queries.CountryStatisticsAggregates +{ + public class + LoadCountryStatisticsAggregatesForCountryInYearQuery : IRequest> + { + public LoadCountryStatisticsAggregatesForCountryInYearQuery(string country, int year) + { + this.Country = country; + this.Year = year; + + if (string.IsNullOrWhiteSpace(this.Country)) throw new ArgumentNullException(nameof(country)); + } + + public string Country { get; } + public int Year { get; } + } +} \ No newline at end of file diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalGlobalStatisticsQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatistics/LoadHistoricalGlobalStatisticsQuery.cs similarity index 90% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalGlobalStatisticsQuery.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatistics/LoadHistoricalGlobalStatisticsQuery.cs index 9cd70f0..0e8796d 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadHistoricalGlobalStatisticsQuery.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatistics/LoadHistoricalGlobalStatisticsQuery.cs @@ -5,7 +5,7 @@ using Covid19Api.UseCases.Abstractions.Models; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.GlobalStatistics { public class LoadHistoricalGlobalStatisticsQuery : ICacheableRequest, IRequest> { diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestGlobalStatisticsQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatistics/LoadLatestGlobalStatisticsQuery.cs similarity index 86% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestGlobalStatisticsQuery.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatistics/LoadLatestGlobalStatisticsQuery.cs index cb8178f..59f066b 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadLatestGlobalStatisticsQuery.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatistics/LoadLatestGlobalStatisticsQuery.cs @@ -4,7 +4,7 @@ using Covid19Api.UseCases.Abstractions.Models; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.GlobalStatistics { public class LoadLatestGlobalStatisticsQuery : ICacheableRequest, IRequest { diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/LoadGlobalStatisticsAggregate.cs b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregate.cs similarity index 82% rename from src/Covid19Api.UseCases.Abstractions/Queries/LoadGlobalStatisticsAggregate.cs rename to src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregate.cs index c9fad59..6cdf436 100644 --- a/src/Covid19Api.UseCases.Abstractions/Queries/LoadGlobalStatisticsAggregate.cs +++ b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregate.cs @@ -1,7 +1,7 @@ using Covid19Api.Presentation.Response; using MediatR; -namespace Covid19Api.UseCases.Abstractions.Queries +namespace Covid19Api.UseCases.Abstractions.Queries.GlobalStatisticsAggregates { public class LoadGlobalStatisticsAggregate : IRequest { diff --git a/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregatesForYearQuery.cs b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregatesForYearQuery.cs new file mode 100644 index 0000000..1de8b46 --- /dev/null +++ b/src/Covid19Api.UseCases.Abstractions/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregatesForYearQuery.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Covid19Api.Presentation.Response; +using MediatR; + +namespace Covid19Api.UseCases.Abstractions.Queries.GlobalStatisticsAggregates +{ + public class LoadGlobalStatisticsAggregatesForYearQuery : IRequest> + { + public LoadGlobalStatisticsAggregatesForYearQuery(int year) + { + this.Year = year; + } + + public int Year { get; } + } +} \ No newline at end of file diff --git a/src/Covid19Api.UseCases/Queries/LoadHistoricalCountriesStatisticsQueryHandler.cs b/src/Covid19Api.UseCases/Queries/CountryStatistics/LoadHistoricalCountriesStatisticsQueryHandler.cs similarity index 90% rename from src/Covid19Api.UseCases/Queries/LoadHistoricalCountriesStatisticsQueryHandler.cs rename to src/Covid19Api.UseCases/Queries/CountryStatistics/LoadHistoricalCountriesStatisticsQueryHandler.cs index d833a47..15e3f2d 100644 --- a/src/Covid19Api.UseCases/Queries/LoadHistoricalCountriesStatisticsQueryHandler.cs +++ b/src/Covid19Api.UseCases/Queries/CountryStatistics/LoadHistoricalCountriesStatisticsQueryHandler.cs @@ -4,10 +4,10 @@ using AutoMapper; using Covid19Api.Presentation.Response; using Covid19Api.Repositories.Abstractions; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatistics; using MediatR; -namespace Covid19Api.UseCases.Queries +namespace Covid19Api.UseCases.Queries.CountryStatistics { public class LoadHistoricalCountriesStatisticsQueryHandler : IRequestHandler> diff --git a/src/Covid19Api.UseCases/Queries/LoadHistoricalStatisticsForCountryQueryHandler.cs b/src/Covid19Api.UseCases/Queries/CountryStatistics/LoadHistoricalCountryStatisticsForCountryQueryHandler.cs similarity index 71% rename from src/Covid19Api.UseCases/Queries/LoadHistoricalStatisticsForCountryQueryHandler.cs rename to src/Covid19Api.UseCases/Queries/CountryStatistics/LoadHistoricalCountryStatisticsForCountryQueryHandler.cs index fb98b83..968b621 100644 --- a/src/Covid19Api.UseCases/Queries/LoadHistoricalStatisticsForCountryQueryHandler.cs +++ b/src/Covid19Api.UseCases/Queries/CountryStatistics/LoadHistoricalCountryStatisticsForCountryQueryHandler.cs @@ -5,26 +5,28 @@ using AutoMapper; using Covid19Api.Presentation.Response; using Covid19Api.Repositories.Abstractions; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatistics; using MediatR; -namespace Covid19Api.UseCases.Queries +namespace Covid19Api.UseCases.Queries.CountryStatistics { public class - LoadHistoricalStatisticsForCountryQueryHandler : IRequestHandler> { private readonly IMapper mapper; private readonly ICountryStatisticsRepository countryStatisticsRepository; - public LoadHistoricalStatisticsForCountryQueryHandler(IMapper mapper, + public LoadHistoricalCountryStatisticsForCountryQueryHandler(IMapper mapper, ICountryStatisticsRepository countryStatisticsRepository) { this.mapper = mapper; this.countryStatisticsRepository = countryStatisticsRepository; } - public async Task> Handle(LoadHistoricalStatisticsForCountryQuery request, + public async Task> Handle( + LoadHistoricalCountryStatisticsForCountryQuery request, CancellationToken cancellationToken) { var minFetchedAt = DateTime.UtcNow.Date.AddDays(-9); diff --git a/src/Covid19Api.UseCases/Queries/LoadLatestCountriesStatisticsQueryHandler.cs b/src/Covid19Api.UseCases/Queries/CountryStatistics/LoadLatestCountriesStatisticsQueryHandler.cs similarity index 91% rename from src/Covid19Api.UseCases/Queries/LoadLatestCountriesStatisticsQueryHandler.cs rename to src/Covid19Api.UseCases/Queries/CountryStatistics/LoadLatestCountriesStatisticsQueryHandler.cs index f06a0ce..cd975d2 100644 --- a/src/Covid19Api.UseCases/Queries/LoadLatestCountriesStatisticsQueryHandler.cs +++ b/src/Covid19Api.UseCases/Queries/CountryStatistics/LoadLatestCountriesStatisticsQueryHandler.cs @@ -6,11 +6,11 @@ using AutoMapper; using Covid19Api.Presentation.Response; using Covid19Api.Services.Abstractions.Loader; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatistics; using Covid19Api.UseCases.Filter; using MediatR; -namespace Covid19Api.UseCases.Queries +namespace Covid19Api.UseCases.Queries.CountryStatistics { public class LoadLatestCountriesStatisticsQueryHandler : IRequestHandler { private readonly IMapper mapper; private readonly IHtmlDocumentLoader htmlDocumentLoader; private readonly ICountryStatisticsLoader countryStatisticsLoader; - public LoadLatestStatisticsForCountryQueryHandler(IMapper mapper, IHtmlDocumentLoader htmlDocumentLoader, + public LoadLatestCountryStatisticsForCountryQueryHandler(IMapper mapper, IHtmlDocumentLoader htmlDocumentLoader, ICountryStatisticsLoader countryStatisticsLoader) { this.mapper = mapper; diff --git a/src/Covid19Api.UseCases/Queries/LoadCountryStatisticsAggregateQueryHandler.cs b/src/Covid19Api.UseCases/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregateQueryHandler.cs similarity index 90% rename from src/Covid19Api.UseCases/Queries/LoadCountryStatisticsAggregateQueryHandler.cs rename to src/Covid19Api.UseCases/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregateQueryHandler.cs index aab1d67..9149cda 100644 --- a/src/Covid19Api.UseCases/Queries/LoadCountryStatisticsAggregateQueryHandler.cs +++ b/src/Covid19Api.UseCases/Queries/CountryStatisticsAggregates/LoadCountryStatisticsAggregateQueryHandler.cs @@ -3,10 +3,10 @@ using AutoMapper; using Covid19Api.Presentation.Response; using Covid19Api.Repositories.Abstractions; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatisticsAggregates; using MediatR; -namespace Covid19Api.UseCases.Queries +namespace Covid19Api.UseCases.Queries.CountryStatisticsAggregates { public class LoadCountryStatisticsAggregateQueryHandler : IRequestHandler> + { + private readonly IMapper mapper; + private readonly ICountryStatisticsAggregatesRepository countryStatisticsAggregatesRepository; + + public LoadCountryStatisticsAggregatesForCountryInYearQueryHandler(IMapper mapper, + ICountryStatisticsAggregatesRepository countryStatisticsAggregatesRepository) + { + this.mapper = mapper; + this.countryStatisticsAggregatesRepository = countryStatisticsAggregatesRepository; + } + + public async Task> Handle( + LoadCountryStatisticsAggregatesForCountryInYearQuery request, CancellationToken cancellationToken) + { + var aggregates = + await this.countryStatisticsAggregatesRepository.FindForCountryInYearAsync(request.Country, + request.Year); + + return aggregates.Any() + ? this.mapper.Map>(aggregates) + : Array.Empty(); + } + } +} \ No newline at end of file diff --git a/src/Covid19Api.UseCases/Queries/LoadHistoricalGlobalStatisticsQueryHandler.cs b/src/Covid19Api.UseCases/Queries/GlobalStatistics/LoadHistoricalGlobalStatisticsQueryHandler.cs similarity index 90% rename from src/Covid19Api.UseCases/Queries/LoadHistoricalGlobalStatisticsQueryHandler.cs rename to src/Covid19Api.UseCases/Queries/GlobalStatistics/LoadHistoricalGlobalStatisticsQueryHandler.cs index 98815e9..5811acf 100644 --- a/src/Covid19Api.UseCases/Queries/LoadHistoricalGlobalStatisticsQueryHandler.cs +++ b/src/Covid19Api.UseCases/Queries/GlobalStatistics/LoadHistoricalGlobalStatisticsQueryHandler.cs @@ -4,10 +4,10 @@ using AutoMapper; using Covid19Api.Presentation.Response; using Covid19Api.Repositories.Abstractions; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.GlobalStatistics; using MediatR; -namespace Covid19Api.UseCases.Queries +namespace Covid19Api.UseCases.Queries.GlobalStatistics { public class LoadHistoricalGlobalStatisticsQueryHandler : IRequestHandler diff --git a/src/Covid19Api.UseCases/Queries/LoadGlobalStatisticsAggregateQueryHandler.cs b/src/Covid19Api.UseCases/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregateQueryHandler.cs similarity index 89% rename from src/Covid19Api.UseCases/Queries/LoadGlobalStatisticsAggregateQueryHandler.cs rename to src/Covid19Api.UseCases/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregateQueryHandler.cs index 17ed4f9..5434815 100644 --- a/src/Covid19Api.UseCases/Queries/LoadGlobalStatisticsAggregateQueryHandler.cs +++ b/src/Covid19Api.UseCases/Queries/GlobalStatisticsAggregates/LoadGlobalStatisticsAggregateQueryHandler.cs @@ -3,10 +3,10 @@ using AutoMapper; using Covid19Api.Presentation.Response; using Covid19Api.Repositories.Abstractions; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.GlobalStatisticsAggregates; using MediatR; -namespace Covid19Api.UseCases.Queries +namespace Covid19Api.UseCases.Queries.GlobalStatisticsAggregates { public class LoadGlobalStatisticsAggregateQueryHandler : IRequestHandler> + { + private readonly IMapper mapper; + private readonly IGlobalStatisticsAggregatesRepository globalStatisticsAggregatesRepository; + + public LoadGlobalStatisticsAggregatesForYearQueryHandler(IMapper mapper, + IGlobalStatisticsAggregatesRepository globalStatisticsAggregatesRepository) + { + this.mapper = mapper; + this.globalStatisticsAggregatesRepository = globalStatisticsAggregatesRepository; + } + + public async Task> Handle( + LoadGlobalStatisticsAggregatesForYearQuery request, CancellationToken cancellationToken) + { + var aggregates = await this.globalStatisticsAggregatesRepository.FindInYearAsync(request.Year); + + return aggregates.Any() + ? this.mapper.Map>(aggregates) + : Array.Empty(); + } + } +} \ No newline at end of file diff --git a/src/Covid19Api.Worker/CountryStatisticsAggregateWorker.cs b/src/Covid19Api.Worker/CountryStatisticsAggregateWorker.cs index 161b44e..320661e 100644 --- a/src/Covid19Api.Worker/CountryStatisticsAggregateWorker.cs +++ b/src/Covid19Api.Worker/CountryStatisticsAggregateWorker.cs @@ -3,7 +3,7 @@ using System.Threading; using System.Threading.Tasks; using Covid19Api.UseCases.Abstractions.Commands; -using Covid19Api.UseCases.Abstractions.Queries; +using Covid19Api.UseCases.Abstractions.Queries.CountryStatistics; using MediatR; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/src/Covid19Api/Startup.cs b/src/Covid19Api/Startup.cs index fbf2cc0..c779c16 100644 --- a/src/Covid19Api/Startup.cs +++ b/src/Covid19Api/Startup.cs @@ -8,7 +8,7 @@ using Covid19Api.IoC.Extensions; using Covid19Api.Middleware; using Covid19Api.UseCases.Behaviors; -using Covid19Api.UseCases.Queries; +using Covid19Api.UseCases.Queries.GlobalStatistics; using MediatR.Extensions.Autofac.DependencyInjection; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting;