Skip to content

Commit 12b9dc4

Browse files
committed
fix: fix several bugs
1 parent d928653 commit 12b9dc4

File tree

116 files changed

+465
-1884
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+465
-1884
lines changed

Directory.Packages.props

+11-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<XabarilVersion>8.0.1</XabarilVersion>
1111
<ApiVersioningVersion>8.1.0</ApiVersioningVersion>
1212
<PollyVersion>8.4.1</PollyVersion>
13-
<AspireUnstablePackagesVersion>8.0.2-preview.1.24326.4</AspireUnstablePackagesVersion>
13+
<AspireUnstablePackagesVersion>8.2.0-preview.1.24428.5</AspireUnstablePackagesVersion>
1414
<GrpcVersion>2.65.0</GrpcVersion>
1515
<MassTransitVersion>8.2.5</MassTransitVersion>
1616
</PropertyGroup>
@@ -22,13 +22,12 @@
2222
<PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="$(AspireVersion)" />
2323
<PackageVersion Include="Aspire.Hosting.RabbitMQ" Version="$(AspireVersion)" />
2424
<PackageVersion Include="Aspire.Hosting.Redis" Version="$(AspireVersion)" />
25-
<PackageVersion Include="Aspire.Npgsql" Version="$(AspireVersion)" />
2625
<PackageVersion Include="Aspire.Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(AspireVersion)" />
2726
<PackageVersion Include="Aspire.Azure.Storage.Blobs" Version="$(AspireVersion)" />
2827
<PackageVersion Include="Aspire.Azure.AI.OpenAI" Version="$(AspireUnstablePackagesVersion)" />
2928
<PackageVersion Include="Aspire.StackExchange.Redis" Version="$(AspireVersion)" />
3029
<PackageVersion Include="Aspire.StackExchange.Redis.OutputCaching" Version="$(AspireVersion)" />
31-
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="$(MicrosoftExtensionsVersion)" />
30+
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="8.9.1" />
3231
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="$(AspireVersion)" />
3332
<!-- Aspirant -->
3433
<PackageVersion Include="Aspirant.Hosting" Version="$(AspirantVersion)" />
@@ -47,20 +46,19 @@
4746
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="$(AspnetVersion)" />
4847
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="$(AspnetVersion)" />
4948
<!-- Entity Framework Core -->
50-
<PackageVersion Include="Pgvector" Version="0.3.0" />
5149
<PackageVersion Include="Pgvector.EntityFrameworkCore" Version="0.2.1" />
5250
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="$(EfCoreVersion)" />
5351
<PackageVersion Include="EFCore.NamingConventions" Version="8.0.3" />
5452
<PackageVersion Include="EntityFrameworkCore.Exceptions.Common" Version="8.1.3" />
5553
<PackageVersion Include="EntityFrameworkCore.Exceptions.PostgreSQL" Version="8.1.3" />
5654
<!-- Semantic Kernel -->
57-
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.17.2" />
55+
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.19.0" />
5856
<!-- Polly -->
5957
<PackageVersion Include="Polly" Version="$(PollyVersion)" />
6058
<PackageVersion Include="Polly.Extensions" Version="$(PollyVersion)" />
6159
<!-- Ardalis -->
6260
<PackageVersion Include="Ardalis.GuardClauses" Version="4.6.0" />
63-
<PackageVersion Include="Ardalis.Result.AspNetCore" Version="9.1.0" />
61+
<PackageVersion Include="Ardalis.Result.AspNetCore" Version="10.0.0" />
6462
<PackageVersion Include="Ardalis.Specification" Version="8.0.0" />
6563
<PackageVersion Include="Ardalis.Specification.EntityFrameworkCore" Version="8.0.0" />
6664
<!-- OpenTelemetry -->
@@ -80,11 +78,11 @@
8078
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
8179
<PackageVersion Include="Xunit.Combinatorial" Version="1.6.24" />
8280
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
83-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.0" />
84-
<PackageVersion Include="Moq" Version="4.20.70" />
81+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
82+
<PackageVersion Include="Moq" Version="4.20.72" />
8583
<PackageVersion Include="FluentAssertions" Version="7.0.0-alpha.4" />
86-
<PackageVersion Include="ReportGenerator" Version="5.3.8" />
87-
<PackageVersion Include="WireMock.Net.Aspire" Version="1.6.1" />
84+
<PackageVersion Include="ReportGenerator" Version="5.3.9" />
85+
<PackageVersion Include="WireMock.Net.Aspire" Version="1.6.3" />
8886
<!-- Grpc -->
8987
<PackageVersion Include="Grpc.AspNetCore" Version="$(GrpcVersion)" />
9088
<PackageVersion Include="Grpc.AspNetCore.Server.ClientFactory" Version="$(GrpcVersion)" />
@@ -96,8 +94,9 @@
9694
<PackageVersion Include="MassTransit.EntityFrameworkCore" Version="$(MassTransitVersion)" />
9795
<!-- Miscellaneous -->
9896
<PackageVersion Include="Scrutor" Version="4.2.2" />
99-
<PackageVersion Include="MediatR" Version="12.4.0" />
100-
<PackageVersion Include="Marten.AspNetCore" Version="7.26.4" />
97+
<PackageVersion Include="MediatR" Version="12.4.1" />
98+
<PackageVersion Include="MongoDB.Bson" Version="2.28.0" />
99+
<PackageVersion Include="Marten.AspNetCore" Version="7.27.0" />
101100
<PackageVersion Include="FluentEmail.Mailtrap" Version="2.7.0" />
102101
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.7.3" />
103102
<PackageVersion Include="FluentValidation.AspNetCore" Version="11.3.0" />

src/BookWorm.Basket/BookWorm.Basket.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
</ItemGroup>
99

1010
<ItemGroup>
11-
<Protobuf Include="Proto\basket.proto" GrpcServices="Server" />
12-
<Protobuf Include="..\BookWorm.Catalog\Proto\book.proto" GrpcServices="Client" />
11+
<Protobuf Include="Protos\basket.proto" GrpcServices="Server" />
12+
<Protobuf Include="..\BookWorm.Catalog\Protos\book.proto" Link="Protos\book.proto" GrpcServices="Client" />
1313
</ItemGroup>
1414

1515
<ItemGroup>

src/BookWorm.Basket/Extensions/Extensions.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ internal static class Extensions
66
{
77
public static void AddApplicationServices(this IHostApplicationBuilder builder)
88
{
9+
builder.AddServiceDefaults();
10+
911
builder.Services.AddExceptionHandler<ValidationExceptionHandler>();
1012
builder.Services.AddExceptionHandler<NotFoundExceptionHandler>();
1113
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
@@ -40,12 +42,12 @@ public static void AddApplicationServices(this IHostApplicationBuilder builder)
4042
builder.Services.AddSingleton<IBookService, BookService>();
4143

4244
builder.Services.AddGrpc();
43-
4445
builder.Services.AddGrpcClient<GrpcBookClient>(o =>
4546
{
4647
o.Address = new("https+http://catalog-api");
4748
});
4849

50+
builder.Services.AddHttpContextAccessor();
4951
builder.Services.AddTransient<IIdentityService, IdentityService>();
5052
}
5153
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Security.Claims;
2+
3+
namespace BookWorm.Basket.Extensions;
4+
5+
internal static class ServerCallContextIdentityExtensions
6+
{
7+
public static string? GetUserIdentity(this ServerCallContext context)
8+
{
9+
return context.GetHttpContext().User.FindFirst(x => x.Type == ClaimTypes.NameIdentifier)?.Value;
10+
}
11+
12+
public static string? GetUserName(this ServerCallContext context)
13+
{
14+
return context.GetHttpContext().User.FindFirst(x => x.Type == ClaimTypes.Name)?.Value;
15+
}
16+
}

src/BookWorm.Basket/Features/Get/GetBasketEndpoint.cs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ public void MapEndpoint(IEndpointRouteBuilder app)
66
{
77
app.MapGet("/baskets", async (ISender sender) => await HandleAsync(sender))
88
.Produces<Ok<BasketDto>>()
9-
.ProducesProblem(StatusCodes.Status404NotFound)
109
.WithTags(nameof(Basket))
1110
.WithName("Get Basket")
1211
.MapToApiVersion(new(1, 0))

src/BookWorm.Basket/Features/Get/GetBasketQuery.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ public async Task<Result<BasketDto>> Handle(GetBasketQuery query, CancellationTo
1717

1818
var basket = await redisService.HashGetAsync<BasketModel?>(nameof(Basket), customerId);
1919

20-
Guard.Against.NotFound(customerId, basket);
20+
if (basket is null)
21+
{
22+
return Result.NotFound();
23+
}
2124

2225
var basketDto = new BasketDto(basket.AccountId, [], 0.0m);
2326

src/BookWorm.Basket/GlobalUsings.cs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
global using System.Text.Json;
44
global using Ardalis.GuardClauses;
55
global using Ardalis.Result;
6+
global using BookWorm.Basket.Extensions;
67
global using BookWorm.Basket.Grpc;
78
global using BookWorm.Basket.Infrastructure.Redis;
89
global using BookWorm.Constants;

src/BookWorm.Basket/Grpc/BasketService.cs

+13-16
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
using GrpcBasketBase = BookWorm.Basket.Grpc.Basket.BasketBase;
2-
using BasketModel = BookWorm.Basket.Domain.Basket;
1+
using BookWorm.Basket.Features;
2+
using BookWorm.Basket.Features.Get;
3+
using GrpcBasketBase = BookWorm.Basket.Grpc.Basket.BasketBase;
34

45
namespace BookWorm.Basket.Grpc;
56

6-
public sealed class BasketService(IRedisService redisService, IBookService bookService, ILogger<BasketService> logger)
7+
public sealed class BasketService(ISender sender, IBookService bookService, ILogger<BasketService> logger)
78
: GrpcBasketBase
89
{
910
[AllowAnonymous]
@@ -15,29 +16,25 @@ public override async Task<BasketResponse> GetBasket(BasketRequest request, Serv
1516
nameof(BasketService), nameof(GetBasket), request.BasketId);
1617
}
1718

18-
var basket = await redisService.HashGetAsync<BasketModel?>(nameof(Basket), request.BasketId);
19+
var userId = context.GetUserIdentity();
1920

20-
if (basket is null)
21+
if (string.IsNullOrEmpty(userId))
2122
{
22-
ThrowNotFound();
23+
return new();
2324
}
2425

25-
return await MapToBasketResponse(basket);
26-
}
26+
var basket = await sender.Send(new GetBasketQuery());
2727

28-
[DoesNotReturn]
29-
private static void ThrowNotFound()
30-
{
31-
throw new RpcException(new(StatusCode.NotFound, "Basket not found"));
28+
return basket.Value is not null ? await MapToBasketResponse(basket.Value) : new();
3229
}
3330

34-
private async Task<BasketResponse> MapToBasketResponse(BasketModel basket)
31+
private async Task<BasketResponse> MapToBasketResponse(BasketDto basket)
3532
{
36-
var response = new BasketResponse { BasketId = basket.AccountId.ToString(), TotalPrice = 0.0 };
33+
var response = new BasketResponse { BasketId = basket.Id.ToString(), TotalPrice = 0.0 };
3734

38-
foreach (var item in basket.BasketItems)
35+
foreach (var item in basket.Items)
3936
{
40-
var book = await bookService.GetBookAsync(item.Id);
37+
var book = await bookService.GetBookAsync(item.BookId);
4138

4239
response.Books.Add(new Book
4340
{

src/BookWorm.Basket/Program.cs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
using BookWorm.Basket.Extensions;
1+
var builder = WebApplication.CreateBuilder(args);
22

3-
var builder = WebApplication.CreateBuilder(args);
4-
5-
builder.AddServiceDefaults()
6-
.AddApplicationServices();
3+
builder.AddApplicationServices();
74

85
var app = builder.Build();
96

src/BookWorm.Catalog/BookWorm.Catalog.csproj

+6-8
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,29 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Pgvector" />
9-
<PackageReference Include="Pgvector.EntityFrameworkCore" />
108
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
11-
<PackageReference Include="Polly" />
12-
<PackageReference Include="Polly.Extensions" />
9+
<PackageReference Include="Microsoft.SemanticKernel" />
10+
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" />
1311
</ItemGroup>
1412

1513
<ItemGroup>
1614
<PackageReference Include="Aspire.Azure.AI.OpenAI" />
17-
<PackageReference Include="Aspire.Npgsql" />
1815
<PackageReference Include="Aspire.Npgsql.EntityFrameworkCore.PostgreSQL" />
1916
<PackageReference Include="Aspire.Azure.Storage.Blobs" />
2017
<PackageReference Include="Aspire.StackExchange.Redis.OutputCaching" />
2118
</ItemGroup>
2219

2320
<ItemGroup>
21+
<PackageReference Include="Polly" />
22+
<PackageReference Include="Polly.Extensions" />
23+
<PackageReference Include="Pgvector.EntityFrameworkCore" />
2424
<PackageReference Include="Grpc.AspNetCore" />
25-
<PackageReference Include="Microsoft.SemanticKernel" />
26-
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" />
2725
<PackageReference Include="EFCore.NamingConventions" />
2826
<PackageReference Include="EntityFrameworkCore.Exceptions.PostgreSQL" />
2927
</ItemGroup>
3028

3129
<ItemGroup>
32-
<Protobuf Include="Proto\book.proto" GrpcServices="Server" />
30+
<Protobuf Include="Protos\book.proto" GrpcServices="Server" />
3331
</ItemGroup>
3432

3533
<ItemGroup>

src/BookWorm.Catalog/Extensions/Extensions.cs

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ internal static class Extensions
44
{
55
public static void AddApplicationServices(this IHostApplicationBuilder builder)
66
{
7+
builder.AddServiceDefaults();
8+
79
builder.AddRedisOutputCache(ServiceName.Redis);
810

911
builder.Services.AddGrpc();
@@ -38,6 +40,8 @@ public static void AddApplicationServices(this IHostApplicationBuilder builder)
3840
builder.Services.AddSingleton<CommandHandlerMetrics>();
3941
builder.Services.AddSingleton<QueryHandlerMetrics>();
4042

43+
builder.Services.AddHttpContextAccessor();
44+
4145
builder.AddRabbitMqEventBus(typeof(global::Program), cfg =>
4246
{
4347
cfg.AddInMemoryInboxOutbox();

src/BookWorm.Catalog/Features/Books/Get/GetBookEndpoint.cs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ public void MapEndpoint(IEndpointRouteBuilder app)
99
app.MapGet("/books/{id:guid}",
1010
async (Guid id, ISender sender) => await HandleAsync(id, sender))
1111
.Produces<Ok<BookDto>>()
12-
.ProducesProblem(StatusCodes.Status404NotFound)
1312
.CacheOutput(policy => policy.Expire(TimeSpan.FromMinutes(20)).SetVaryByRouteValue("id"))
1413
.WithTags(nameof(Book))
1514
.WithName("Get Book")

src/BookWorm.Catalog/Features/Books/Get/GetBookQuery.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ public async Task<Result<Book>> Handle(GetBookQuery request, CancellationToken c
1111
{
1212
var book = await repository.FirstOrDefaultAsync(new BookFilterSpec(request.Id), cancellationToken);
1313

14-
Guard.Against.NotFound(request.Id, book);
14+
if (book is null)
15+
{
16+
return Result.NotFound();
17+
}
1518

1619
return book;
1720
}

src/BookWorm.Catalog/Features/Books/List/ListBooksQuery.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public async Task<PagedResult<IEnumerable<Book>>> Handle(ListBooksQuery request,
3939

4040
var books = await repository.ListAsync(spec, cancellationToken);
4141

42-
var totalRecords = await repository.CountAsync(spec, cancellationToken);
42+
var totalRecords = await repository.CountAsync(cancellationToken);
4343

4444
var totalPages = (int)Math.Ceiling(totalRecords / (double)request.PageSize);
4545

src/BookWorm.Catalog/Grpc/BookService.cs

+6-26
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,36 @@
1-
using BookWorm.Catalog.Domain.BookAggregate.Specifications;
1+
using BookWorm.Catalog.Features.Books.Get;
22
using Grpc.Core;
33
using GrpcBookServer = BookWorm.Catalog.Grpc.Book.BookBase;
44
using BookModel = BookWorm.Catalog.Domain.BookAggregate.Book;
55

66
namespace BookWorm.Catalog.Grpc;
77

8-
public sealed class BookService(IReadRepository<BookModel> repository, ILogger<BookService> logger) : GrpcBookServer
8+
public sealed class BookService(ISender sender, ILogger<BookService> logger) : GrpcBookServer
99
{
1010
[AllowAnonymous]
1111
public override async Task<BookResponse> GetBook(BookRequest request, ServerCallContext context)
1212
{
13-
BookFilterSpec spec = new(Guid.Parse(request.BookId));
14-
1513
if (logger.IsEnabled(LogLevel.Debug))
1614
{
1715
logger.LogDebug("[{Service}] - Getting book with id: {Id}", nameof(BookService), request.BookId);
1816
}
1917

20-
var book = await repository.FirstOrDefaultAsync(spec);
21-
22-
if (book is null)
23-
{
24-
ThrowNotFound();
25-
}
18+
var book = await sender.Send(new GetBookQuery(Guid.Parse(request.BookId)), context.CancellationToken);
2619

27-
return MapToBookResponse(book);
20+
return book.Value is not null ? MapToBookResponse(book.Value) : new();
2821
}
2922

3023
[AllowAnonymous]
3124
public override async Task<BookStatusResponse> GetBookStatus(BookStatusRequest request, ServerCallContext context)
3225
{
33-
BookFilterSpec spec = new(Guid.Parse(request.BookId));
34-
3526
if (logger.IsEnabled(LogLevel.Debug))
3627
{
3728
logger.LogDebug("[{Service}] - Getting book status with id: {Id}", nameof(BookService), request.BookId);
3829
}
3930

40-
var book = await repository.FirstOrDefaultAsync(spec);
31+
var book = await sender.Send(new GetBookQuery(Guid.Parse(request.BookId)), context.CancellationToken);
4132

42-
if (book is null)
43-
{
44-
ThrowNotFound();
45-
}
46-
47-
return MapToBookStatusResponse(book);
48-
}
49-
50-
[DoesNotReturn]
51-
private static void ThrowNotFound()
52-
{
53-
throw new RpcException(new(StatusCode.NotFound, "Book not found"));
33+
return book.Value is not null ? MapToBookStatusResponse(book.Value) : new();
5434
}
5535

5636
private static BookResponse MapToBookResponse(BookModel book)

src/BookWorm.Catalog/Infrastructure/Ai/AiService.cs

-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ public async ValueTask<Vector> GetEmbeddingAsync(string text, CancellationToken
1313

1414
var embedding = await embeddingGenerator.GenerateEmbeddingAsync(text, cancellationToken: cancellationToken);
1515

16-
1716
embedding = embedding[..EmbeddingDimensions];
1817

1918
if (logger.IsEnabled(LogLevel.Trace))
@@ -22,7 +21,6 @@ public async ValueTask<Vector> GetEmbeddingAsync(string text, CancellationToken
2221
Stopwatch.GetElapsedTime(timestamp).TotalSeconds, text);
2322
}
2423

25-
2624
return new(embedding);
2725
}
2826

@@ -41,7 +39,6 @@ public async ValueTask<IReadOnlyList<Vector>> GetEmbeddingsAsync(List<string> te
4139
Stopwatch.GetElapsedTime(timestamp).TotalSeconds);
4240
}
4341

44-
4542
return results;
4643
}
4744
}

0 commit comments

Comments
 (0)