diff --git a/cart-service/src/main/java/com/drinkool/controllers/CartController.java b/cart-service/src/main/java/com/drinkool/controllers/CartController.java index d6dfd1e..5037f92 100644 --- a/cart-service/src/main/java/com/drinkool/controllers/CartController.java +++ b/cart-service/src/main/java/com/drinkool/controllers/CartController.java @@ -6,6 +6,7 @@ import static io.smallrye.graphql.client.core.Field.field; import static io.smallrye.graphql.client.core.Operation.operation; import com.drinkool.dtos.CartItemRequest; +import com.drinkool.dtos.event.MenuItemValidation; import io.quarkus.redis.datasource.ReactiveRedisDataSource; import io.quarkus.redis.datasource.hash.ReactiveHashCommands; import io.quarkus.redis.datasource.keys.ReactiveKeyCommands; @@ -21,6 +22,7 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.UUID; +import org.eclipse.microprofile.reactive.messaging.Incoming; @Path("/") public class CartController { @@ -41,7 +43,7 @@ public class CartController { this.redisDataSource = ds; this.valueCommands = ds.value(String.class); this.hashCommands = ds.hash(String.class); - this.keyCommands = ds.key(); + this.keyCommands = ds.key(); } @POST @@ -58,16 +60,16 @@ public class CartController { return valueCommands .get(eateryCacheKey) - .chain((String existsInCache) -> { - if (existsInCache != null && existsInCache.equals("true")) { - return Uni.createFrom().item(Boolean.TRUE); - } + .chain(existsInCache -> { + if ( + existsInCache != null && Boolean.TRUE.equals(existsInCache) + ) return Uni.createFrom().item(Boolean.TRUE); var query = document( operation( field( "eateryById", - List.of(arg("id", eateryId.toString())), // Bọc arg vào List.of() + List.of(arg("id", eateryId.toString())), field("id") ) ) @@ -75,28 +77,21 @@ public class CartController { return dynamicClient .executeAsync(query) - .map(response -> { - if (response.hasError()) { - return false; - } - - var data = response.getData(); - return data != null && !data.isNull("eateryById"); - }); + .map(response -> !response.hasError() && response.getData() != null); }) - .map((Boolean isValid) -> { - if (isValid) { + .chain(isValid -> { + if (Boolean.TRUE.equals(isValid)) { String cartId = UUID.randomUUID().toString(); - valueCommands + return valueCommands .setex("cart:" + cartId, 86400, eateryId.toString()) - .subscribe() - .with(item -> {}); - return Response.ok(cartId).build(); - } else { - return Response.status(Response.Status.NOT_FOUND) - .entity("EateryNotFound") - .build(); + .replaceWith(Response.ok(cartId).build()); } + + return Uni.createFrom().item( + Response.status(Response.Status.NOT_FOUND) + .entity("InvalidEateryId") + .build() + ); }); } @@ -121,25 +116,27 @@ public class CartController { ); } + UUID eateryId = UUID.fromString(cart); + return valueCommands .get(menuKey) - .chain(menuData -> { - return hashCommands + .chain(menuData -> + hashCommands .hincrby( cartItemsKey, request.menuItemId.toString(), request.quantity ) - .call(_ -> keyCommands.expire(cartItemsKey, 86400)) - .map(b -> menuData); - }) + .call(_ -> keyCommands.expire(cartItemsKey, 86400L)) + .replaceWith(menuData) + ) .map(menuData -> { if (menuData != null) { return Response.ok("ItemAdded").build(); } validationEmitter.send( - new MenuItemValidationEvent(request.menuItemId, cartId) + new MenuItemValidation(request.menuItemId, eateryId) ); return Response.status(Response.Status.ACCEPTED) @@ -148,4 +145,22 @@ public class CartController { }); }); } + + @Incoming("menu-validation-results") // Tên channel trong application.properties + public Uni processValidationResult(MenuItemStatusEvent event) { + // Giả sử event trả về có: menuItemId, eateryId, exists (boolean) + + if (!event.exists) { + // Nếu món ăn không tồn tại, ta xóa nó khỏi Redis + // Lưu ý: Vì ta không biết món này nằm ở cartId nào (do bạn yêu cầu bỏ cartId) + // Bạn sẽ cần một chiến lược tìm kiếm hoặc quản lý key hiệu quả. + // Cách 1: Nếu bạn có danh sách Cart của Eatery đó, duyệt qua và xóa: + // String cartItemsKey = "cart:" + event.cartId + ":items"; + // return hashCommands.hdel(cartItemsKey, event.menuItemId.toString()).replaceWithVoid(); + // Cách 2: Nếu xóa cache thông tin món ăn để các request sau cũng fail: + // return keyCommands.del("menu:item:" + event.menuItemId).replaceWithVoid(); + } + + return Uni.createFrom().voidItem(); + } } diff --git a/lib/src/main/java/com/drinkool/Url.java b/lib/src/main/java/com/drinkool/Url.java index e547d3c..f3dd0b5 100644 --- a/lib/src/main/java/com/drinkool/Url.java +++ b/lib/src/main/java/com/drinkool/Url.java @@ -9,4 +9,5 @@ public class Url { public static final String SmsOtp = "/sms_otp"; public static final String Me = "/me"; public static final String Logout = "/logout"; + public static final String Cart = "/cart"; } diff --git a/lib/src/main/java/com/drinkool/dtos/CartItemRequest.java b/lib/src/main/java/com/drinkool/dtos/CartItemRequest.java new file mode 100644 index 0000000..6798953 --- /dev/null +++ b/lib/src/main/java/com/drinkool/dtos/CartItemRequest.java @@ -0,0 +1,9 @@ +package com.drinkool.dtos; + +import java.util.UUID; + +public class CartItemRequest { + + public UUID menuItemId; + public int quantity; +} diff --git a/lib/src/main/java/com/drinkool/dtos/event/MenuItemValidation.java b/lib/src/main/java/com/drinkool/dtos/event/MenuItemValidation.java new file mode 100644 index 0000000..7d4d8a5 --- /dev/null +++ b/lib/src/main/java/com/drinkool/dtos/event/MenuItemValidation.java @@ -0,0 +1,17 @@ +package com.drinkool.dtos.event; + +import io.quarkus.runtime.annotations.RegisterForReflection; +import java.util.UUID; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@RegisterForReflection +@Getter +@Setter +@NoArgsConstructor +public class MenuItemValidation { + + public UUID menuItemId; + public UUID eateryId; +}