diff --git a/springAdvance/DistributionLock/SpringDistributionLock/README.md b/springAdvance/DistributionLock/SpringDistributionLock/README.md
index 3637c8466..6f045535a 100644
--- a/springAdvance/DistributionLock/SpringDistributionLock/README.md
+++ b/springAdvance/DistributionLock/SpringDistributionLock/README.md
@@ -69,6 +69,9 @@ brew services start redis
brew services stop redis
+# reload nginx config
+nginx -s reload
+
#---------------------------
# Intellij
#---------------------------
diff --git a/springWarehouse/README.md b/springWarehouse/README.md
index bbbfa03d0..1f2f4d8e7 100644
--- a/springWarehouse/README.md
+++ b/springWarehouse/README.md
@@ -18,6 +18,8 @@ ARCHITECTURE :
- V1

+- V2
+ - Cluster mode with Nginx
[Demo](http://43.206.107.101:7777/)
@@ -70,7 +72,41 @@ ARCHITECTURE :
mvn package
# run
-java -jar target/springWarehouse-0.0.1-SNAPSHOT.jar
+# https://blog.csdn.net/G971005287W/article/details/114879972
+java -jar target/springWarehouse-0.0.1-SNAPSHOT.jar --server.port=7777
+java -jar target/springWarehouse-0.0.1-SNAPSHOT.jar --server.port=7778
+
+#---------------------------
+# Run nginx
+#---------------------------
+
+# https://github.com/yennanliu/utility_shell/blob/master/nginx/install_nginx.sh
+# http://localhost:8080/
+
+# start
+brew services start nginx
+
+# stop
+brew services stop nginx
+
+
+#---------------------------
+# Other cmd
+#---------------------------
+
+# reload nginx config
+nginx -s reload
+
+# kill progress uses port
+lsof -i :
+kill
+
+# pressure testing - jmeter
+cd apache-jmeter-5.6.2
+bash bin/jmeter
+
+# curl
+curl http://localhost:7777/productType/list?pageNoStr=1
```
@@ -148,10 +184,15 @@ nohup java -jar target/springWarehouse-0.0.1-SNAPSHOT.jar &
## API
-| API | Type | Purpose | Example cmd | Comment|
-| ----- | -------- | ---- | ----- | ---- |
-| http://localhost:7777/ | Get | Home page || |
-| http://localhost:7777/swagger-ui/index.html | Get | API doc page || |
+| API | Type | Purpose | Example cmd | Comment|
+|-----------------------------------------------------|---------------| ---- | ----- | ---- |
+| http://localhost:7777/ | Get | Home page || |
+| http://localhost:7777/swagger-ui/index.html | Get | API doc page || |
+| http://localhost:7777/test/type | test endpoint | | |
+| http://localhost:7777/test/prod | test endpoint | | |
+| http://localhost:7777/test/prod/deduct/{product_id} | test endpoint | | |
+| http://localhost:8080/ | Nginx endpoint | | |
+
## Important Concepts
diff --git a/springWarehouse/nginx/nginx.conf b/springWarehouse/nginx/nginx.conf
new file mode 100644
index 000000000..29189931c
--- /dev/null
+++ b/springWarehouse/nginx/nginx.conf
@@ -0,0 +1,93 @@
+
+# https://youtu.be/CDaWk2RIBL4?si=dfe4B7Ct4fsPSOGW&t=315
+# https://github.com/yennanliu/utility_shell/blob/master/nginx/nginx_backup.conf
+
+#user nobody;
+worker_processes 1;
+
+#error_log logs/error.log;
+#error_log logs/error.log notice;
+#error_log logs/error.log info;
+
+#pid logs/nginx.pid;
+
+
+events {
+ worker_connections 1024;
+}
+
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ # '$status $body_bytes_sent "$http_referer" '
+ # '"$http_user_agent" "$http_x_forwarded_for"';
+
+ #access_log logs/access.log main;
+
+ sendfile on;
+ #tcp_nopush on;
+
+ #keepalive_timeout 0;
+ keepalive_timeout 65;
+
+ #gzip on;
+
+ # load balance, reverse proxy
+ # https://youtu.be/CDaWk2RIBL4?si=k5piBHOSF-7vNTh1&t=392
+ upstream warehouseService {
+ server localhost:7777;
+ server localhost:7778;
+ }
+
+ server {
+ listen 8080;
+ server_name localhost;
+
+ location / {
+# root html;
+# index index.html index.htm;
+ proxy_pass http://warehouseService;
+ }
+
+ }
+
+
+ # another virtual host using mix of IP-, name-, and port-based configuration
+ #
+ #server {
+ # listen 8000;
+ # listen somename:8080;
+ # server_name somename alias another.alias;
+
+ # location / {
+ # root html;
+ # index index.html index.htm;
+ # }
+ #}
+
+
+ # HTTPS server
+ #
+ #server {
+ # listen 443 ssl;
+ # server_name localhost;
+
+ # ssl_certificate cert.pem;
+ # ssl_certificate_key cert.key;
+
+ # ssl_session_cache shared:SSL:1m;
+ # ssl_session_timeout 5m;
+
+ # ssl_ciphers HIGH:!aNULL:!MD5;
+ # ssl_prefer_server_ciphers on;
+
+ # location / {
+ # root html;
+ # index index.html index.htm;
+ # }
+ #}
+ include servers/*;
+}
\ No newline at end of file
diff --git a/springWarehouse/sql/ddl/product.sql b/springWarehouse/sql/ddl/product.sql
index a066db6c9..2ab442dbb 100644
--- a/springWarehouse/sql/ddl/product.sql
+++ b/springWarehouse/sql/ddl/product.sql
@@ -3,20 +3,25 @@
-- create database warehouse_system;
+-- DROP TABLE product;
+
CREATE TABLE IF NOT EXISTS product(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(100) not null,
- type_id int not null,
+ type_id int DEFAULT 1,
price int not null,
merchant_id varchar(100),
product_status varchar(10),
- amount int DEFAULT 0,
- constraint FK_PRODUCT_TYPE FOREIGN KEY (type_id) references product_type(type_id)
+ amount int DEFAULT 0
+ -- constraint FK_PRODUCT_TYPE FOREIGN KEY (type_id) references product_type(type_id)
);
-- DML
-INSERT INTO product(name, type_id, price, merchant_id, amount, product_status)
+-- truncate product;
+
+INSERT INTO product(name, price, merchant_id, amount, product_status)
VALUES
-("i-phone", 2, 300, 1, 3, "on_board"),
-("cookie2", 4, 10, 2, 2, "new"),
-("soap", 1, 50, 1, 1, "off_board");
\ No newline at end of file
+("i-phone", 300, 1, 5000, "on_board"),
+("cookie2", 10, 2, 5000, "new"),
+("soap", 50, 3, 5000, "off_board"),
+("soap", 70, 4, 5000, "off_board");
\ No newline at end of file
diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/controller/OrderController.java b/springWarehouse/src/main/java/com/yen/springWarehouse/controller/OrderController.java
index 18b82ccbf..1b8a60b42 100644
--- a/springWarehouse/src/main/java/com/yen/springWarehouse/controller/OrderController.java
+++ b/springWarehouse/src/main/java/com/yen/springWarehouse/controller/OrderController.java
@@ -120,6 +120,7 @@ public String update(Order order) {
*/
@GetMapping(value="/download")
public void download(){
+
List orders = orderService.getAllOrders();
}
diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/controller/TestController.java b/springWarehouse/src/main/java/com/yen/springWarehouse/controller/TestController.java
new file mode 100644
index 000000000..63c021597
--- /dev/null
+++ b/springWarehouse/src/main/java/com/yen/springWarehouse/controller/TestController.java
@@ -0,0 +1,50 @@
+package com.yen.springWarehouse.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.yen.springWarehouse.bean.Product;
+import com.yen.springWarehouse.bean.ProductType;
+import com.yen.springWarehouse.service.ProductService;
+import com.yen.springWarehouse.service.ProductTypeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RequestMapping("/test")
+@RestController
+public class TestController {
+
+ @Autowired
+ ProductTypeService productTypeService;
+
+ @Autowired
+ ProductService productService;
+
+
+ /** productType */
+ @GetMapping("/type")
+ List getAllProductType(){
+
+ return productTypeService.list(new QueryWrapper<>());
+ }
+
+
+ /** product */
+ @GetMapping("/prod")
+ List getAllProduct(){
+
+ return productService.list(new QueryWrapper<>());
+ }
+
+ @GetMapping("/prod/deduct/{productId}")
+ String deductProduct(@PathVariable("productId") Integer productId){
+
+ productService.deduct(productId);
+ return "OK";
+ }
+
+}
diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/mapper/ProductMapper.java b/springWarehouse/src/main/java/com/yen/springWarehouse/mapper/ProductMapper.java
index df4782459..20d9d0b7d 100644
--- a/springWarehouse/src/main/java/com/yen/springWarehouse/mapper/ProductMapper.java
+++ b/springWarehouse/src/main/java/com/yen/springWarehouse/mapper/ProductMapper.java
@@ -6,6 +6,7 @@
import com.yen.springWarehouse.bean.Product;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
import java.util.List;
@@ -16,4 +17,6 @@ public interface ProductMapper extends BaseMapper {
// TODO : check @Param("ew") ??
List getProductList(Page productPage, @Param("ew") Wrapper wrapper);
+ @Update("update product set amount = amount - #{amount} where id = #{productId} and amount >= #{amount}")
+ int updateProductCount(@Param("productId") Integer productId, @Param("amount") Integer amount);
}
diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/service/ProductService.java b/springWarehouse/src/main/java/com/yen/springWarehouse/service/ProductService.java
index 376e32fb8..1b2ff7f3c 100644
--- a/springWarehouse/src/main/java/com/yen/springWarehouse/service/ProductService.java
+++ b/springWarehouse/src/main/java/com/yen/springWarehouse/service/ProductService.java
@@ -15,4 +15,5 @@ public interface ProductService extends IService {
List getProductDtoListFromProductList(List productList);
+ void deduct(Integer id);
}
diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductServiceImpl.java b/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductServiceImpl.java
index 13e3e9ac3..b774b502d 100644
--- a/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductServiceImpl.java
+++ b/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductServiceImpl.java
@@ -1,6 +1,7 @@
package com.yen.springWarehouse.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -30,6 +31,9 @@ public class ProductServiceImpl extends ServiceImpl impl
@Autowired
ProductTypeMapper productTypeMapper;
+ @Autowired
+ ProductMapper productMapper;
+
@Autowired
MerchantService merchantService;
@@ -94,4 +98,25 @@ public List getProductDtoListFromProductList(List productLi
return productDtoList;
}
+ @Override
+ public void deduct(Integer id) {
+
+ /** V1 */
+ System.out.println(">>> id = " + id);
+ Product product = productMapper.selectById(id);
+ System.out.println(">>> product = " + product);
+ int amount = product.getAmount();
+
+// product.setAmount(amount-1);
+// UpdateWrapper wrapper = new UpdateWrapper<>(product);
+// // TODO : check why productMapper CAN'T update with UpdateWrapper
+// //productMapper.update(product, wrapper); //baseMapper.update(product, wrapper);
+// productMapper.updateById(product);
+
+ /** V2 : use Mysql lock deal with cluster deployment */
+
+ productMapper.updateProductCount(product.getId(), 1);
+ System.out.println(">>> product = " + product);
+ }
+
}
diff --git a/springWarehouse/src/main/resources/application.properties b/springWarehouse/src/main/resources/application.properties
index 2211bf3ad..815379fcc 100644
--- a/springWarehouse/src/main/resources/application.properties
+++ b/springWarehouse/src/main/resources/application.properties
@@ -4,11 +4,11 @@ debug=true
server.tomcat.uri-encoding=UTF-8
spring-http-encoding.charset=UTF-8
# hot deployment
-spring.devtools.restart.enabled=true
-spring.thymeleaf.mode=HTML5
-spring.thymeleaf.encoding=UTF-8
-spring.thymeleaf.cache=false
-spring.thymeleaf.suffix=.html
+#spring.devtools.restart.enabled=true
+#spring.thymeleaf.mode=HTML5
+#spring.thymeleaf.encoding=UTF-8
+#spring.thymeleaf.cache=false
+#spring.thymeleaf.suffix=.html
# mysql
spring.datasource.url=jdbc:mysql://localhost:3306/warehouse_system?createDatabaseIfNotExist=true