Skip to content

Commit 5079976

Browse files
committed
Added aggregate root and tracking support.
1 parent 3eb0ea1 commit 5079976

39 files changed

Lines changed: 826 additions & 33 deletions

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ services:
3939
networks:
4040
- cdp-tenant
4141
ports:
42-
- '27017:27017'
42+
- '27018:27017'
4343
volumes:
4444
- mongodb-data:/data
4545
restart: always
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Asp.Versioning;
2+
using KeeperData.Application;
3+
using KeeperData.Application.Queries.Sites;
4+
using Microsoft.AspNetCore.Mvc;
5+
6+
namespace KeeperData.Api.Controllers
7+
{
8+
[ApiController]
9+
[ApiVersion("1.0")]
10+
[Route("api/v{version:apiVersion}/[controller]")]
11+
public class SiteController(IRequestExecutor executor) : ControllerBase
12+
{
13+
private readonly IRequestExecutor _executor = executor;
14+
15+
[HttpGet("{id}")]
16+
public async Task<IActionResult> GetById(string id)
17+
{
18+
var result = await _executor.ExecuteQuery(new GetSiteByIdQuery(id));
19+
return Ok(result);
20+
}
21+
}
22+
}

src/KeeperData.Api/KeeperData.Api.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
</ItemGroup>
1717

1818
<ItemGroup>
19+
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
1920
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
2021
</ItemGroup>
2122

src/KeeperData.Api/Program.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,6 @@ static void ConfigureBuilder(WebApplicationBuilder builder)
5555
}
5656
});
5757

58-
builder.Services.AddControllers()
59-
.AddJsonOptions(opts =>
60-
{
61-
var enumConverter = new JsonStringEnumConverter();
62-
opts.JsonSerializerOptions.Converters.Add(enumConverter);
63-
});
64-
6558
builder.Services.ConfigureApi(builder.Configuration);
6659
}
6760

src/KeeperData.Api/Setup/ServiceCollectionExtensions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,34 @@
1+
using Asp.Versioning;
12
using KeeperData.Application.Setup;
23
using KeeperData.Infrastructure.Database.Setup;
34
using KeeperData.Infrastructure.Messaging.Setup;
5+
using System.Text.Json.Serialization;
46

57
namespace KeeperData.Api.Setup;
68

79
public static class ServiceCollectionExtensions
810
{
911
public static void ConfigureApi(this IServiceCollection services, IConfiguration configuration)
1012
{
13+
services.AddControllers()
14+
.AddJsonOptions(opts =>
15+
{
16+
var enumConverter = new JsonStringEnumConverter();
17+
opts.JsonSerializerOptions.Converters.Add(enumConverter);
18+
});
19+
20+
services.AddApiVersioning(options =>
21+
{
22+
options.ApiVersionReader = new UrlSegmentApiVersionReader();
23+
options.DefaultApiVersion = new ApiVersion(1, 0);
24+
options.ReportApiVersions = true;
25+
})
26+
.AddApiExplorer(options =>
27+
{
28+
options.GroupNameFormat = "'v'VVV";
29+
options.SubstituteApiVersionInUrl = true;
30+
});
31+
1132
services.AddDefaultAWSOptions(configuration.GetAWSOptions());
1233

1334
services.ConfigureHealthChecks();

src/KeeperData.Api/Setup/WebApplicationExtensions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ public static void ConfigureRequestPipeline(this WebApplication app)
2121
applicationLifetime.ApplicationStopped.Register(() =>
2222
logger.LogInformation("{applicationName} stopped", env.ApplicationName));
2323

24+
var versionSet = app.NewApiVersionSet()
25+
.HasApiVersion(new Asp.Versioning.ApiVersion(1.0))
26+
.ReportApiVersions()
27+
.Build();
28+
2429
app.UseMiddleware<ExceptionHandlingMiddleware>();
2530

2631
app.UseHeaderPropagation();
@@ -40,9 +45,9 @@ public static void ConfigureRequestPipeline(this WebApplication app)
4045
[HealthStatus.Degraded] = StatusCodes.Status200OK,
4146
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
4247
}
43-
});
48+
}).WithApiVersionSet(versionSet).IsApiVersionNeutral();
4449

45-
app.MapGet("/", () => "Alive!");
50+
app.MapGet("/", () => "Alive!").WithApiVersionSet(versionSet).IsApiVersionNeutral();
4651

4752
app.MapControllers();
4853
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using KeeperData.Core.Domain.BuildingBlocks.Aggregates;
2+
using MediatR;
3+
4+
namespace KeeperData.Application.Commands;
5+
6+
public interface ITrackedCommandHandler<in TCommand, TResult>
7+
: IRequestHandler<TCommand, TrackedResult<TResult>> where TCommand
8+
: ICommand<TrackedResult<TResult>>
9+
{
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using KeeperData.Core.Domain.BuildingBlocks.Aggregates;
2+
3+
namespace KeeperData.Application.Commands.Sites;
4+
5+
/// <summary>
6+
/// Example implementation only. To remove in future stories.
7+
/// </summary>
8+
/// <param name="Name"></param>
9+
public record CreateSiteCommand(string Name) : ICommand<TrackedResult<string>>;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using KeeperData.Core.Documents;
2+
using KeeperData.Core.Domain.BuildingBlocks.Aggregates;
3+
using KeeperData.Core.Domain.Sites;
4+
using KeeperData.Core.Repositories;
5+
6+
namespace KeeperData.Application.Commands.Sites;
7+
8+
/// <summary>
9+
/// Example implementation only. To remove in future stories.
10+
/// </summary>
11+
/// <param name="repository"></param>
12+
public class CreateSiteCommandHandler(IGenericRepository<SiteDocument> repository)
13+
: ITrackedCommandHandler<CreateSiteCommand, string>
14+
{
15+
private readonly IGenericRepository<SiteDocument> _repository = repository;
16+
17+
public async Task<TrackedResult<string>> Handle(CreateSiteCommand request, CancellationToken cancellationToken)
18+
{
19+
var site = Site.Create(Guid.NewGuid().ToString(), "Holding", request.Name, "England");
20+
site.AddSiteIdentifier(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "CPH");
21+
22+
var document = SiteDocument.FromDomain(site);
23+
await _repository.AddAsync(document, cancellationToken);
24+
25+
return new TrackedResult<string>(site.Id, site);
26+
}
27+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using KeeperData.Application.Commands;
22
using KeeperData.Application.Queries;
3+
using KeeperData.Core.Domain.BuildingBlocks.Aggregates;
34

45
namespace KeeperData.Application;
56

67
public interface IRequestExecutor
78
{
89
Task<TResponse> ExecuteCommand<TResponse>(ICommand<TResponse> command, CancellationToken cancellationToken = default);
10+
Task<TResponse> ExecuteCommand<TResponse>(ICommand<TrackedResult<TResponse>> command, CancellationToken cancellationToken = default);
11+
Task<TrackedResult<TResponse>> ExecuteTrackedCommand<TResponse>(ICommand<TrackedResult<TResponse>> command, CancellationToken cancellationToken = default);
912
Task<TResponse> ExecuteQuery<TResponse>(IQuery<TResponse> query, CancellationToken cancellationToken = default);
1013
}

0 commit comments

Comments
 (0)