Files
backend/cart-service/src/main/java/com/drinkool/services/CartService.java
T
2026-05-12 02:27:26 +00:00

162 lines
4.1 KiB
Java

package com.drinkool.services;
import com.drinkool.InternalValue;
import com.drinkool.controllers.EateryController;
import com.drinkool.dtos.Cart;
import com.drinkool.dtos.CartItem;
import io.quarkus.redis.datasource.RedisDataSource;
import io.quarkus.redis.datasource.hash.HashCommands;
import io.quarkus.redis.datasource.value.ValueCommands;
import io.smallrye.mutiny.Uni;
import io.vertx.core.http.HttpServerRequest;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.graphql.GraphQLApi;
import org.eclipse.microprofile.graphql.GraphQLException;
import org.eclipse.microprofile.graphql.Mutation;
import org.eclipse.microprofile.graphql.Name;
import org.eclipse.microprofile.graphql.Query;
import org.eclipse.microprofile.rest.client.inject.RestClient;
@ApplicationScoped
@GraphQLApi
public class CartService {
@Inject
HttpServerRequest request;
@Inject
@RestClient
EateryController eateryController;
private final HashCommands<String, String, String> hashCommands;
private final ValueCommands<String, String> valueCommands;
@Inject
public CartService(RedisDataSource ds) {
this.hashCommands = ds.hash(String.class);
this.valueCommands = ds.value(String.class);
}
@Mutation("createCart")
public Uni<String> createCart(@Name("eateryId") UUID eateryId) {
String userId = request.getHeader(InternalValue.userId);
return eateryController
.getEateryById(eateryId)
.onItem()
.transform(response -> {
if (response.getStatus() != Response.Status.OK.getStatusCode()) {
throw new RuntimeException("NotFoundEatery");
}
String cartId = UUID.randomUUID().toString();
String redisKey = "cart:" + cartId;
String ownerId = response.readEntity(String.class);
hashCommands.hset(
redisKey,
Map.of(
"_metadata_owner",
userId != null ? userId : "GUEST",
"_metadata_eatery",
eateryId.toString(),
"_metadata_ownerId",
ownerId
)
);
valueCommands
.getDataSource()
.key()
.expire(redisKey, Duration.ofDays(30));
return cartId;
})
.onFailure()
.transform(f ->
new GraphQLException(
"Lỗi kết nối đến dịch vụ nhà hàng: " + f.getMessage()
)
);
}
@Query("getCart")
public Cart getCart(@Name("cartId") UUID cartId) throws GraphQLException {
String key = "cart:" + cartId;
Map<String, String> data = hashCommands.hgetall(key);
if (data.isEmpty()) {
throw new GraphQLException("NotFoundCart");
}
List<CartItem> items = new ArrayList<>();
data.forEach((k, v) -> {
if (!k.startsWith("_")) {
items.add(new CartItem(k, Integer.parseInt(v)));
}
});
return new Cart(
cartId,
UUID.fromString(data.get("_metadata_owner")),
UUID.fromString(data.get("_metadata_eatery")),
items
);
}
@Mutation("addItem")
public Uni<Cart> addItem(
@Name("cartId") UUID cartId,
@Name("menuItemId") UUID menuItemId,
@Name("quantity") long quantity
) {
String key = "cart:" + cartId;
String priceKey = "cart_prices:" + cartId;
String eateryIdStr = hashCommands.hget(key, "_metadata_eatery");
if (eateryIdStr == null) throw new RuntimeException("CartNotFound");
UUID eateryId = UUID.fromString(eateryIdStr);
return eateryController
.checkMenuItemExists(eateryId, menuItemId)
.onItem()
.transform(response -> {
if (response.getStatus() != Response.Status.OK.getStatusCode()) {
throw new RuntimeException("NotFoundMenuItemInEatery");
}
Double menuItemPrice = response.readEntity(Double.class);
hashCommands.hincrby(key, menuItemId.toString(), quantity);
hashCommands.hset(
priceKey,
menuItemId.toString(),
String.valueOf(menuItemPrice)
);
hashCommands.getDataSource().key().expire(key, Duration.ofDays(30));
hashCommands
.getDataSource()
.key()
.expire(priceKey, Duration.ofDays(30));
try {
return getCart(cartId);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
});
}
}