فهرست منبع

Merge remote-tracking branch 'origin/并发优化' into dev

# Conflicts:
#	src/main/java/com/izouma/nineth/domain/Order.java
#	src/main/java/com/izouma/nineth/web/OrderController.java
xiongzhu 4 سال پیش
والد
کامیت
36cf6e976c

+ 33 - 0
src/main/bench/index.js

@@ -0,0 +1,33 @@
+const axios = require("axios");
+const qs = require("qs");
+setInterval(() => {}, 1 << 30);
+
+axios.defaults.baseURL = "http://localhost:8080";
+axios
+    .post(
+        "/auth/phonePwdLogin",
+        qs.stringify({ phone: "15077886171", password: "123456" })
+    )
+    .then((res) => {
+        console.log(res.data);
+        axios.defaults.headers["Authorization"] = "Bearer " + res.data;
+        axios.get("/user/my").then((res) => {
+            console.log(res.data);
+        });
+        for (let i = 0; i < 10000; i++) {
+            axios
+                .post(
+                    "/order/create",
+                    qs.stringify({ collectionId: 7669, qty: 1 })
+                )
+                .then((res) => {
+                    console.log(res.data);
+                    setTimeout(() => {
+                        axios.post(
+                            "/order/testNotify",
+                            qs.stringify({ id: res.data.id })
+                        );
+                    }, Math.random() * 1000 + 100);
+                });
+        }
+    });

+ 6 - 0
src/main/bench/package.json

@@ -0,0 +1,6 @@
+{
+  "dependencies": {
+    "axios": "^0.24.0",
+    "qs": "^6.10.2"
+  }
+}

+ 70 - 0
src/main/bench/yarn.lock

@@ -0,0 +1,70 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+axios@^0.24.0:
+  version "0.24.0"
+  resolved "https://registry.npmmirror.com/axios/download/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
+  integrity sha1-gE5voeS5xSiFAd2d/1anoJQNINY=
+  dependencies:
+    follow-redirects "^1.14.4"
+
+call-bind@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.nlark.com/call-bind/download/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+  integrity sha1-sdTonmiBGcPJqQOtMKuy9qkZvjw=
+  dependencies:
+    function-bind "^1.1.1"
+    get-intrinsic "^1.0.2"
+
+follow-redirects@^1.14.4:
+  version "1.14.6"
+  resolved "https://registry.npmmirror.com/follow-redirects/download/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd"
+  integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==
+
+function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+  integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=
+
+get-intrinsic@^1.0.2:
+  version "1.1.1"
+  resolved "https://registry.nlark.com/get-intrinsic/download/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
+  integrity sha1-FfWfN2+FXERpY5SPDSTNNje0q8Y=
+  dependencies:
+    function-bind "^1.1.1"
+    has "^1.0.3"
+    has-symbols "^1.0.1"
+
+has-symbols@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.nlark.com/has-symbols/download/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
+  integrity sha1-Fl0wcMADCXUqEjakeTMeOsVvFCM=
+
+has@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.nlark.com/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=
+  dependencies:
+    function-bind "^1.1.1"
+
+object-inspect@^1.9.0:
+  version "1.11.1"
+  resolved "https://registry.npmmirror.com/object-inspect/download/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b"
+  integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==
+
+qs@^6.10.2:
+  version "6.10.2"
+  resolved "https://registry.npmmirror.com/qs/download/qs-6.10.2.tgz#c1431bea37fc5b24c5bdbafa20f16bdf2a4b9ffe"
+  integrity sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==
+  dependencies:
+    side-channel "^1.0.4"
+
+side-channel@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.nlark.com/side-channel/download/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+  integrity sha1-785cj9wQTudRslxY1CkAEfpeos8=
+  dependencies:
+    call-bind "^1.0.0"
+    get-intrinsic "^1.0.2"
+    object-inspect "^1.9.0"

+ 34 - 0
src/main/java/com/izouma/nineth/repo/CollectionRepo.java

@@ -31,6 +31,7 @@ public interface CollectionRepo extends JpaRepository<Collection, Long>, JpaSpec
     @Query("update Collection t set t.likes = t.likes + ?2 where t.id = ?1")
     @Modifying
     @Transactional
+    @CacheEvict(value = "collection", key = "#id")
     void addLike(Long id, int num);
 
     @Query(value = "select distinct c from Collection c join Like l on l.collectionId = c.id " +
@@ -46,4 +47,37 @@ public interface CollectionRepo extends JpaRepository<Collection, Long>, JpaSpec
     @Query("select new com.izouma.nineth.dto.RecommendCollection(c,r) from Collection c join Recommend r on c.id = r.collectionId " +
             "where c.del = false and c.onShelf = true and r.type = ?1 order by r.sort desc")
     List<RecommendCollection> recommend(String type);
+
+    @Transactional
+    @Modifying
+    @Query("update Collection c set c.currentNumber = COALESCE(c.currentNumber, 0) + ?2 where c.id = ?1")
+    @CacheEvict(value = "collection", key = "#id")
+    void increaseNumber(Long id, int d);
+
+    @Transactional
+    @Modifying
+    @Query("update Collection c set c.sale = COALESCE(c.sale, 0) + ?2 where c.id = ?1")
+    @CacheEvict(value = "collection", key = "#id")
+    void increaseSale(Long id, int d);
+
+    @Transactional
+    @Modifying
+    @Query("update Collection c set c.stock = COALESCE(c.stock, 0) + ?2 where c.id = ?1")
+    @CacheEvict(value = "collection", key = "#id")
+    void increaseStock(Long id, int d);
+
+    @Transactional
+    @Modifying
+    @Query("update Collection c set c.total = COALESCE(c.total, 0) + ?2 where c.id = ?1")
+    @CacheEvict(value = "collection", key = "#id")
+    void increaseTotal(Long id, int d);
+
+    @Transactional
+    @Modifying
+    @Query("update Collection c set c.onShelf = ?2 where c.id = ?1")
+    @CacheEvict(value = "collection", key = "#id")
+    void setOnShelf(Long id, boolean onShelf);
+
+    @Query("select c.currentNumber from Collection c where c.id = ?1")
+    Optional<Integer> getCurrentNumber(Long id);
 }

+ 5 - 0
src/main/java/com/izouma/nineth/repo/UserRepo.java

@@ -158,4 +158,9 @@ public interface UserRepo extends JpaRepository<User, Long>, JpaSpecificationExe
     void setSales(Long userId, int sales);
 
     List<User> findByAuthoritiesContains(Authority authority);
+
+    @Transactional
+    @Modifying
+    @Query("update User u set u.sales = COALESCE(u.sales, 0) + ?2 where u.id = ?1")
+    public void increaseSales(Long id, int num);
 }

+ 3 - 4
src/main/java/com/izouma/nineth/service/AirDropService.java

@@ -58,11 +58,10 @@ public class AirDropService {
                         BlindBoxItem winItem = collectionService.draw(collection.getId());
                         assetService.createAsset(winItem, user, null, null, "空投", collectionService.getNextNumber(winItem.getCollectionId()));
                     } else {
-                        assetService.createAsset(collection, user, null, null, "空投", collectionService.getNextNumber(collection));
+                        assetService.createAsset(collection, user, null, null, "空投", collectionService.getNextNumber(collection.getId()));
                     }
-                    collection.setStock(collection.getStock() - 1);
-                    collection.setSale(collection.getSale() + 1);
-                    collectionRepo.save(collection);
+                    collectionRepo.increaseStock(collection.getId(), -1);
+                    collectionRepo.increaseSale(collection.getId(), 1);
                 } catch (Exception e) {
                     log.error("空投出错", e);
                 }

+ 16 - 1
src/main/java/com/izouma/nineth/service/AssetMintService.java

@@ -10,6 +10,7 @@ import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.AssetRepo;
 import com.izouma.nineth.repo.TokenHistoryRepo;
 import com.izouma.nineth.repo.UserRepo;
+import com.izouma.nineth.utils.SnowflakeIdWorker;
 import io.ipfs.api.IPFS;
 import io.ipfs.api.MerkleNode;
 import io.ipfs.api.NamedStreamable;
@@ -22,7 +23,8 @@ import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.math.BigInteger;
+import java.util.Arrays;
 
 @Service
 @Slf4j
@@ -36,6 +38,19 @@ public class AssetMintService {
     private Environment        env;
 
     public void mint(Asset asset, Long historyId) {
+        if (Arrays.stream(env.getActiveProfiles()).anyMatch(s -> s.equals("dev"))) {
+            asset.setTokenId(new SnowflakeIdWorker(0, 1).nextId() + "");
+            asset.setBlockNumber(new BigInteger("1"));
+            asset.setTxHash("1");
+            asset.setGasUsed(new BigInteger("1"));
+            if (asset.getIpfsUrl() == null) {
+                asset.setIpfsUrl(ipfsUpload(asset.getPic().get(0).getUrl()));
+            }
+            assetRepo.save(asset);
+            applicationContext.publishEvent(new CreateAssetEvent(this, true, asset));
+            return;
+        }
+
         User user = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
         if (StringUtils.isEmpty(user.getPublicKey())) {
             NFTAccount account = nftService.createAccount(user.getUsername() + "_");

+ 6 - 24
src/main/java/com/izouma/nineth/service/CollectionService.java

@@ -173,8 +173,7 @@ public class CollectionService {
         for (BlindBoxItem item : createBlindBox.getItems()) {
             Collection collection = list.stream().filter(i -> i.getId().equals(item.getCollectionId())).findAny()
                     .orElseThrow(new BusinessException("所选藏品不存在"));
-            collection.setStock(collection.getStock() - item.getTotal());
-            collectionRepo.save(collection);
+            collectionRepo.increaseStock(collection.getId(), -item.getTotal());
             BlindBoxItem blindBoxItem = new BlindBoxItem();
             BeanUtils.copyProperties(collection, blindBoxItem);
             blindBoxItem.setId(null);
@@ -210,9 +209,8 @@ public class CollectionService {
     public void scheduleOnShelf() {
         List<Collection> collections = collectionRepo.findByScheduleSaleTrueAndOnShelfFalseAndStartTimeBeforeAndDelFalse(LocalDateTime.now());
         for (Collection collection : collections) {
-            collection.setOnShelf(true);
+            collectionRepo.setOnShelf(collection.getId(), true);
         }
-        collectionRepo.saveAll(collections);
     }
 
 
@@ -271,24 +269,8 @@ public class CollectionService {
     }
 
     public synchronized Integer getNextNumber(Long collectionId) {
-        Collection collection = collectionRepo.findById(collectionId).orElse(null);
-        if (collection == null) return 0;
-        if (collection.getCurrentNumber() == null) {
-            collection.setCurrentNumber(0);
-        }
-        collection.setCurrentNumber(collection.getCurrentNumber() + 1);
-        collectionRepo.save(collection);
-        return collection.getCurrentNumber();
-    }
-
-    public synchronized Integer getNextNumber(Collection collection) {
-        if (collection == null) return 0;
-        if (collection.getCurrentNumber() == null) {
-            collection.setCurrentNumber(0);
-        }
-        collection.setCurrentNumber(collection.getCurrentNumber() + 1);
-        collectionRepo.save(collection);
-        return collection.getCurrentNumber();
+        collectionRepo.increaseNumber(collectionId, 1);
+        return collectionRepo.getCurrentNumber(collectionId).orElse(0);
     }
 
     public void addStock(Long id, int number) {
@@ -299,7 +281,7 @@ public class CollectionService {
         if (collection.getType() == CollectionType.BLIND_BOX) {
             throw new BusinessException("盲盒无法增发");
         }
-        collection.setStock(collection.getStock() + number);
-        collection.setTotal(collection.getTotal() + number);
+        collectionRepo.increaseStock(id, number);
+        collectionRepo.increaseTotal(id, number);
     }
 }

+ 10 - 16
src/main/java/com/izouma/nineth/service/OrderService.java

@@ -116,9 +116,8 @@ public class OrderService {
             userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
         }
 
-        collection.setStock(collection.getStock() - qty);
-        collection.setSale(collection.getSale() + qty);
-        collectionRepo.save(collection);
+        collectionRepo.increaseStock(collectionId, -qty);
+        collectionRepo.increaseSale(collectionId, qty);
 
         BigDecimal gasFee = sysConfigService.getBigDecimal("gas_fee");
         Order order = Order.builder()
@@ -164,8 +163,7 @@ public class OrderService {
             Asset asset = assetRepo.findById(collection.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
             asset.setStatus(AssetStatus.TRADING);
             assetRepo.save(asset);
-            collection.setOnShelf(false);
-            collectionRepo.save(collection);
+            collectionRepo.setOnShelf(collectionId, false);
         }
         order = orderRepo.save(order);
         if (order.getTotalPrice().equals(BigDecimal.ZERO)) {
@@ -391,7 +389,7 @@ public class OrderService {
                 orderRepo.save(order);
                 assetService.createAsset(winItem, user, order.getId(), order.getPrice(), "出售",
                         collectionService.getNextNumber(winItem.getCollectionId()));
-                addSales(winItem.getMinterId());
+                addSales(winItem.getMinterId(), order.getQty());
             } else {
                 if (collection.getSource() == CollectionSource.TRANSFER) {
                     Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
@@ -402,7 +400,7 @@ public class OrderService {
                     assetService.createAsset(collection, user, order.getId(), order.getPrice(), "出售",
                             collectionService.getNextNumber(order.getCollectionId()));
                 }
-                addSales(collection.getMinterId());
+                addSales(collection.getMinterId(), order.getQty());
             }
             commission(order);
         } else if (order.getStatus() == OrderStatus.CANCELLED) {
@@ -458,11 +456,10 @@ public class OrderService {
                 asset.setStatus(AssetStatus.NORMAL);
                 assetRepo.save(asset);
             }
-            collection.setOnShelf(true);
+            collectionRepo.setOnShelf(collection.getId(), true);
         }
-        collection.setSale(collection.getSale() - 1);
-        collection.setStock(collection.getStock() + 1);
-        collectionRepo.save(collection);
+        collectionRepo.increaseSale(collection.getId(), -order.getQty());
+        collectionRepo.increaseStock(collection.getId(), order.getQty());
 
         order.setStatus(OrderStatus.CANCELLED);
         order.setCancelTime(LocalDateTime.now());
@@ -492,12 +489,9 @@ public class OrderService {
     public void refundCancelled(Order order) {
     }
 
-    public synchronized void addSales(Long userId) {
+    public synchronized void addSales(Long userId, int num) {
         if (userId != null) {
-            userRepo.findById(userId).ifPresent(user -> {
-                user.setSales(user.getSales() + 1);
-                userRepo.save(user);
-            });
+            userRepo.increaseSales(userId, num);
         }
     }
 

+ 6 - 0
src/main/java/com/izouma/nineth/web/OrderController.java

@@ -12,6 +12,7 @@ import com.izouma.nineth.repo.OrderRepo;
 import com.izouma.nineth.service.OrderService;
 import com.izouma.nineth.utils.ObjUtils;
 import com.izouma.nineth.utils.SecurityUtils;
+import com.izouma.nineth.utils.SnowflakeIdWorker;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.BeanUtils;
@@ -118,5 +119,10 @@ public class OrderController extends BaseController {
             orderRepo.save(order);
         });
     }
+
+    @PostMapping("/testNotify")
+    public void testNotify(@RequestParam Long id) {
+        orderService.notifyOrder(id, PayMethod.ALIPAY, new SnowflakeIdWorker(0, 0).nextId() + "");
+    }
 }
 

+ 3 - 4
src/test/java/com/izouma/nineth/service/OrderServiceTest.java

@@ -113,9 +113,8 @@ public class OrderServiceTest extends ApplicationTests {
                 }
             }
             orderRepo.delete(errOrder);
-            collection.setStock(collection.getStock() + 1);
-            collection.setSale(collection.getSale() - 1);
-            collectionRepo.save(collection);
+            collectionRepo.increaseStock(collection.getId(), 1);
+            collectionRepo.increaseSale(collection.getId(), -1);
         }
     }
 
@@ -167,7 +166,7 @@ public class OrderServiceTest extends ApplicationTests {
 
     @Test
     public void consignmentFix() throws IOException {
-        String s = FileUtils.readFile("/Users/drew/Downloads/app.log").replaceAll("</p>\n","</p>");
+        String s = FileUtils.readFile("/Users/drew/Downloads/app.log").replaceAll("</p>\n", "</p>");
         String[] arr = s.split("\n");
         for (int i = 0; i < arr.length; i++) {
             if (arr[i].contains("insert into collection_info")) {