// Path: demo-service-interface/src/main/java/app/demo/api/ProductWebService.java
// public interface ProductWebService {
//     @GET
//     @Path("/product")
//     SearchProductResponse search(SearchProductRequest request);
// 
//     @GET
//     @Path("/product/:id")
//     Optional<ProductView> get(@PathParam("id") String id);
// 
//     @POST
//     @Path("/product")
//     @ResponseStatus(HTTPStatus.CREATED)
//     void create(CreateProductRequest request);
// 
//     @PATCH
//     @Path("/product/:id")
//     void update(@PathParam("id") String id, UpdateProductRequest request);
// }
// 
// Path: demo-service-interface/src/main/java/app/demo/api/product/ProductView.java
// public class ProductView {
//     @Property(name = "id")
//     public String id;
// 
//     @NotNull(message = "name is required")
//     @Property(name = "name")
//     public String name;
// 
//     @Property(name = "desc")
//     public String description;
// 
//     @Property(name = "created_time")
//     public LocalDateTime createdTime;
// }
// 
// Path: demo-service-interface/src/main/java/app/demo/api/product/kafka/ProductUpdatedMessage.java
// public class ProductUpdatedMessage {
//     @NotNull(message = "id is required")
//     @Property(name = "id")
//     public String id;
// 
//     @NotBlank
//     @Property(name = "name")
//     public String name;
// 
//     @Property(name = "desc")
//     public String desc;
// }
// 
// Path: demo-service/src/main/java/app/demo/product/kafka/ProductUpdatedMessageHandler.java
// public class ProductUpdatedMessageHandler implements MessageHandler<ProductUpdatedMessage> {
//     private final Logger logger = LoggerFactory.getLogger(ProductUpdatedMessageHandler.class);
// 
//     @Override
//     public void handle(String key, ProductUpdatedMessage messages) {
//         logger.debug("{}-{}", key, messages.name);
//     }
// }
// 
// Path: demo-service/src/main/java/app/demo/product/service/ProductService.java
// public class ProductService {
//     private final Map<String, ProductView> products = Maps.newConcurrentHashMap();
//     @Inject
//     Cache<ProductView> cache;
// 
//     public Optional<ProductView> get(String id) {
//         ProductView view = cache.get(id, products::get);
//         return Optional.ofNullable(view);
//     }
// 
//     public void create(CreateProductRequest request) {
//         ProductView product = new ProductView();
//         product.id = request.id;
//         product.name = request.name;
//         product.description = request.description;
//         product.createdTime = LocalDateTime.now();
//         products.put(product.id, product);
//     }
// 
//     public void update(String id, UpdateProductRequest request) {
//         ProductView product = products.get(id);
//         if (product == null) throw new NotFoundException("product not found");
//         if (request.name != null) product.name = request.name;
//     }
// }
// 
// Path: demo-service/src/main/java/app/demo/product/web/ProductUpdatedMessageTestController.java
// public class ProductUpdatedMessageTestController implements Controller {
//     @Inject
//     MessagePublisher<ProductUpdatedMessage> publisher;
// 
//     @Override
//     public Response execute(Request request) {
//         ActionLogContext.triggerTrace(true);
//         for (int i = 0; i < 10; i++) {
//             ProductUpdatedMessage value = new ProductUpdatedMessage();
//             value.id = String.valueOf(i);
//             value.name = "name-" + i;
//             publisher.publish(value.id, value);
//         }
//         return Response.empty();
//     }
// }
// 
// Path: demo-service/src/main/java/app/demo/product/web/ProductWebServiceImpl.java
// public class ProductWebServiceImpl implements ProductWebService {
//     @Inject
//     ProductService productService;
// 
//     @Override
//     public SearchProductResponse search(SearchProductRequest request) {
//         SearchProductResponse response = new SearchProductResponse();
//         response.products = Lists.newArrayList();
//         return response;
//     }
// 
//     @LimitRate("product")
//     @Override
//     public Optional<ProductView> get(String id) {
//         ActionLogContext.put("pid", id);
//         return productService.get(id);
//     }
// 
//     @Override
//     public void create(CreateProductRequest request) {
//         productService.create(request);
//     }
// 
//     @Override
//     public void update(String id, UpdateProductRequest request) {
//         productService.update(id, request);
//     }
// }


import app.demo.api.ProductWebService;
import app.demo.api.product.ProductView;
import app.demo.api.product.kafka.ProductUpdatedMessage;
import app.demo.product.kafka.ProductUpdatedMessageHandler;
import app.demo.product.service.ProductService;
import app.demo.product.web.ProductUpdatedMessageTestController;
import app.demo.product.web.ProductWebServiceImpl;
import core.framework.http.HTTPClient;
import core.framework.module.Module;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import static core.framework.http.HTTPMethod.GET;
package app;




/**
 * @author neo
 */
public class ProductModule extends Module {
    @Override
    protected void initialize() {
        bind(HTTPClient.class, HTTPClient.builder().build());

        cache().add(ProductView.class, Duration.ofHours(2)).local();

        bind(ProductService.class);

//        configureKafka();

        api().service(ProductWebService.class, bind(ProductWebServiceImpl.class));

        http().limitRate()
                .add("product", 3, 20, TimeUnit.MINUTES);
    }

    private void configureKafka() {
        kafka().uri("localhost");

// Path: demo-service-interface/src/main/java/app/demo/api/ProductWebService.java
// public interface ProductWebService {
//     @GET
//     @Path("/product")
//     SearchProductResponse search(SearchProductRequest request);
// 
//     @GET
//     @Path("/product/:id")
//     Optional<ProductView> get(@PathParam("id") String id);
// 
//     @POST
//     @Path("/product")
//     @ResponseStatus(HTTPStatus.CREATED)
//     void create(CreateProductRequest request);
// 
//     @PATCH
//     @Path("/product/:id")
//     void update(@PathParam("id") String id, UpdateProductRequest request);
// }
// 
// Path: demo-service-interface/src/main/java/app/demo/api/product/ProductView.java
// public class ProductView {
//     @Property(name = "id")
//     public String id;
// 
//     @NotNull(message = "name is required")
//     @Property(name = "name")
//     public String name;
// 
//     @Property(name = "desc")
//     public String description;
// 
//     @Property(name = "created_time")
//     public LocalDateTime createdTime;
// }
// 
// Path: demo-service-interface/src/main/java/app/demo/api/product/kafka/ProductUpdatedMessage.java
// public class ProductUpdatedMessage {
//     @NotNull(message = "id is required")
//     @Property(name = "id")
//     public String id;
// 
//     @NotBlank
//     @Property(name = "name")
//     public String name;
// 
//     @Property(name = "desc")
//     public String desc;
// }
// 
// Path: demo-service/src/main/java/app/demo/product/kafka/ProductUpdatedMessageHandler.java
// public class ProductUpdatedMessageHandler implements MessageHandler<ProductUpdatedMessage> {
//     private final Logger logger = LoggerFactory.getLogger(ProductUpdatedMessageHandler.class);
// 
//     @Override
//     public void handle(String key, ProductUpdatedMessage messages) {
//         logger.debug("{}-{}", key, messages.name);
//     }
// }
// 
// Path: demo-service/src/main/java/app/demo/product/service/ProductService.java
// public class ProductService {
//     private final Map<String, ProductView> products = Maps.newConcurrentHashMap();
//     @Inject
//     Cache<ProductView> cache;
// 
//     public Optional<ProductView> get(String id) {
//         ProductView view = cache.get(id, products::get);
//         return Optional.ofNullable(view);
//     }
// 
//     public void create(CreateProductRequest request) {
//         ProductView product = new ProductView();
//         product.id = request.id;
//         product.name = request.name;
//         product.description = request.description;
//         product.createdTime = LocalDateTime.now();
//         products.put(product.id, product);
//     }
// 
//     public void update(String id, UpdateProductRequest request) {
//         ProductView product = products.get(id);
//         if (product == null) throw new NotFoundException("product not found");
//         if (request.name != null) product.name = request.name;
//     }
// }
// 
// Path: demo-service/src/main/java/app/demo/product/web/ProductUpdatedMessageTestController.java
// public class ProductUpdatedMessageTestController implements Controller {
//     @Inject
//     MessagePublisher<ProductUpdatedMessage> publisher;
// 
//     @Override
//     public Response execute(Request request) {
//         ActionLogContext.triggerTrace(true);
//         for (int i = 0; i < 10; i++) {
//             ProductUpdatedMessage value = new ProductUpdatedMessage();
//             value.id = String.valueOf(i);
//             value.name = "name-" + i;
//             publisher.publish(value.id, value);
//         }
//         return Response.empty();
//     }
// }
// 
// Path: demo-service/src/main/java/app/demo/product/web/ProductWebServiceImpl.java
// public class ProductWebServiceImpl implements ProductWebService {
//     @Inject
//     ProductService productService;
// 
//     @Override
//     public SearchProductResponse search(SearchProductRequest request) {
//         SearchProductResponse response = new SearchProductResponse();
//         response.products = Lists.newArrayList();
//         return response;
//     }
// 
//     @LimitRate("product")
//     @Override
//     public Optional<ProductView> get(String id) {
//         ActionLogContext.put("pid", id);
//         return productService.get(id);
//     }
// 
//     @Override
//     public void create(CreateProductRequest request) {
//         productService.create(request);
//     }
// 
//     @Override
//     public void update(String id, UpdateProductRequest request) {
//         productService.update(id, request);
//     }
// }


// Path: demo-service/src/main/java/app/ProductModule.java
import app.demo.api.ProductWebService;
import app.demo.api.product.ProductView;
import app.demo.api.product.kafka.ProductUpdatedMessage;
import app.demo.product.kafka.ProductUpdatedMessageHandler;
import app.demo.product.service.ProductService;
import app.demo.product.web.ProductUpdatedMessageTestController;
import app.demo.product.web.ProductWebServiceImpl;
import core.framework.http.HTTPClient;
import core.framework.module.Module;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import static core.framework.http.HTTPMethod.GET;

package app;




/**
 * @author neo
 */
public class ProductModule extends Module {
    @Override
    protected void initialize() {
        bind(HTTPClient.class, HTTPClient.builder().build());

        cache().add(ProductView.class, Duration.ofHours(2)).local();

        bind(ProductService.class);

//        configureKafka();

        api().service(ProductWebService.class, bind(ProductWebServiceImpl.class));

        http().limitRate()
                .add("product", 3, 20, TimeUnit.MINUTES);
    }

    private void configureKafka() {
        kafka().uri("localhost");

        kafka().subscribe("product-updated", ProductUpdatedMessage.class, bind(ProductUpdatedMessageHandler.class));