From 49f70a82fcf9505080d95c4bc3c9e64d166b4842 Mon Sep 17 00:00:00 2001 From: Caleb Blake Date: Thu, 1 May 2025 13:18:04 -0700 Subject: [PATCH] wip --- src/Basket.API/Basket.API.csproj | 4 ++++ src/Basket.API/Grpc/BasketService.cs | 9 ++++++--- .../OrderStartedIntegrationEventHandler.cs | 2 +- .../Events/OrderStartedIntegrationEvent.cs | 2 +- src/Basket.API/Model/CustomerBasket.cs | 2 ++ src/Basket.API/Proto/basket.proto | 18 ++++++++++++++++++ .../Repositories/IBasketRepository.cs | 8 +++++--- .../Repositories/RedisBasketRepository.cs | 18 ++++++++---------- 8 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/Basket.API/Basket.API.csproj b/src/Basket.API/Basket.API.csproj index 9864d23cc..0fac35d9d 100644 --- a/src/Basket.API/Basket.API.csproj +++ b/src/Basket.API/Basket.API.csproj @@ -7,6 +7,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/src/Basket.API/Grpc/BasketService.cs b/src/Basket.API/Grpc/BasketService.cs index 3f1deda67..c69587507 100644 --- a/src/Basket.API/Grpc/BasketService.cs +++ b/src/Basket.API/Grpc/BasketService.cs @@ -23,7 +23,8 @@ public override async Task GetBasket(GetBasketRequest re logger.LogDebug("Begin GetBasketById call from method {Method} for basket id {Id}", context.Method, userId); } - var data = await repository.GetBasketAsync(userId); + var basketId = request.BasketId; // Extract basketId from the request + var data = await repository.GetBasketAsync(userId, basketId); // Pass both userId and basketId if (data is not null) { @@ -47,7 +48,7 @@ public override async Task UpdateBasket(UpdateBasketRequ } var customerBasket = MapToCustomerBasket(userId, request); - var response = await repository.UpdateBasketAsync(customerBasket); + var response = await repository.UpdateBasketAsync(userId, customerBasket); if (response is null) { ThrowBasketDoesNotExist(userId); @@ -64,7 +65,9 @@ public override async Task DeleteBasket(DeleteBasketReques ThrowNotAuthenticated(); } - await repository.DeleteBasketAsync(userId); + var basketId = request.BasketId; + await repository.DeleteBasketAsync(userId, basketId); + return new(); } diff --git a/src/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs b/src/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs index a503b4e4d..3579c95e2 100644 --- a/src/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs +++ b/src/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs @@ -11,6 +11,6 @@ public async Task Handle(OrderStartedIntegrationEvent @event) { logger.LogInformation("Handling integration event: {IntegrationEventId} - ({@IntegrationEvent})", @event.Id, @event); - await repository.DeleteBasketAsync(@event.UserId); + await repository.DeleteBasketAsync(@event.UserId, @event.BasketId); } } diff --git a/src/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs b/src/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs index 59aadcb20..9d3d6c655 100644 --- a/src/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs +++ b/src/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs @@ -3,4 +3,4 @@ // Integration Events notes: // An Event is "something that has happened in the past", therefore its name has to be // An Integration Event is an event that can cause side effects to other microservices, Bounded-Contexts or external systems. -public record OrderStartedIntegrationEvent(string UserId) : IntegrationEvent; +public record OrderStartedIntegrationEvent(string UserId, string BasketId) : IntegrationEvent; diff --git a/src/Basket.API/Model/CustomerBasket.cs b/src/Basket.API/Model/CustomerBasket.cs index 8ec8828bf..01164753e 100644 --- a/src/Basket.API/Model/CustomerBasket.cs +++ b/src/Basket.API/Model/CustomerBasket.cs @@ -2,6 +2,8 @@ public class CustomerBasket { + public string Id { get; set; } + public string BuyerId { get; set; } public List Items { get; set; } = []; diff --git a/src/Basket.API/Proto/basket.proto b/src/Basket.API/Proto/basket.proto index 67c830ed2..0ff385cf9 100644 --- a/src/Basket.API/Proto/basket.proto +++ b/src/Basket.API/Proto/basket.proto @@ -8,9 +8,12 @@ service Basket { rpc GetBasket(GetBasketRequest) returns (CustomerBasketResponse) {} rpc UpdateBasket(UpdateBasketRequest) returns (CustomerBasketResponse) {} rpc DeleteBasket(DeleteBasketRequest) returns (DeleteBasketResponse) {} + rpc CreateBasket(CreateBasketRequest) returns (CreateBasketResponse) {} + rpc ListBaskets(ListBasketRequest) returns (ListBasketResponse) {} } message GetBasketRequest { + string basket_id = 1; } message CustomerBasketResponse { @@ -22,12 +25,27 @@ message BasketItem { int32 quantity = 6; } +message ListBasketRequest { +} + +message ListBasketResponse { + repeated string basket_ids = 1; +} + message UpdateBasketRequest { repeated BasketItem items = 2; } message DeleteBasketRequest { + string basket_id = 1; } message DeleteBasketResponse { +} + +message CreateBasketRequest { +} + +message CreateBasketResponse { + string basket_id = 1; } \ No newline at end of file diff --git a/src/Basket.API/Repositories/IBasketRepository.cs b/src/Basket.API/Repositories/IBasketRepository.cs index 29f7ec289..bb39ec9ce 100644 --- a/src/Basket.API/Repositories/IBasketRepository.cs +++ b/src/Basket.API/Repositories/IBasketRepository.cs @@ -4,7 +4,9 @@ namespace eShop.Basket.API.Repositories; public interface IBasketRepository { - Task GetBasketAsync(string customerId); - Task UpdateBasketAsync(CustomerBasket basket); - Task DeleteBasketAsync(string id); + Task GetBasketAsync(string customerId, string basketId); + Task UpdateBasketAsync(string customerId, CustomerBasket basket); + Task DeleteBasketAsync(string customerId, string basketId); + Task CreateBasketAsync(string customerId); + Task> ListBasketsAsync(string customerId); } diff --git a/src/Basket.API/Repositories/RedisBasketRepository.cs b/src/Basket.API/Repositories/RedisBasketRepository.cs index 2dc26f370..f3f284aac 100644 --- a/src/Basket.API/Repositories/RedisBasketRepository.cs +++ b/src/Basket.API/Repositories/RedisBasketRepository.cs @@ -13,16 +13,15 @@ public class RedisBasketRepository(ILogger logger, IConne private static RedisKey BasketKeyPrefix = "/basket/"u8.ToArray(); // note on UTF8 here: library limitation (to be fixed) - prefixes are more efficient as blobs - private static RedisKey GetBasketKey(string userId) => BasketKeyPrefix.Append(userId); - - public async Task DeleteBasketAsync(string id) + private static RedisKey GetBasketKey(string userId, string basketId) => BasketKeyPrefix.Append(userId).Append(basketId); + public async Task DeleteBasketAsync(string userId, string basketId) { - return await _database.KeyDeleteAsync(GetBasketKey(id)); + return await _database.KeyDeleteAsync(GetBasketKey(userId, basketId)); } - public async Task GetBasketAsync(string customerId) + public async Task GetBasketAsync(string userId, string basketId) { - using var data = await _database.StringGetLeaseAsync(GetBasketKey(customerId)); + using var data = await _database.StringGetLeaseAsync(GetBasketKey(userId, basketId)); if (data is null || data.Length == 0) { @@ -31,10 +30,10 @@ public async Task GetBasketAsync(string customerId) return JsonSerializer.Deserialize(data.Span, BasketSerializationContext.Default.CustomerBasket); } - public async Task UpdateBasketAsync(CustomerBasket basket) + public async Task UpdateBasketAsync(string userId, CustomerBasket basket) { var json = JsonSerializer.SerializeToUtf8Bytes(basket, BasketSerializationContext.Default.CustomerBasket); - var created = await _database.StringSetAsync(GetBasketKey(basket.BuyerId), json); + var created = await _database.StringSetAsync(GetBasketKey(userId, basket.Id), json); if (!created) { @@ -42,9 +41,8 @@ public async Task UpdateBasketAsync(CustomerBasket basket) return null; } - logger.LogInformation("Basket item persisted successfully."); - return await GetBasketAsync(basket.BuyerId); + return await GetBasketAsync(userId, basket.Id); } }