Authored by LUOXC

添加价格校验

@@ -55,6 +55,7 @@ import java.math.BigDecimal; @@ -55,6 +55,7 @@ import java.math.BigDecimal;
55 import java.util.*; 55 import java.util.*;
56 import java.util.concurrent.ExecutorService; 56 import java.util.concurrent.ExecutorService;
57 import java.util.concurrent.Executors; 57 import java.util.concurrent.Executors;
  58 +import java.util.function.Predicate;
58 import java.util.stream.Collectors; 59 import java.util.stream.Collectors;
59 60
60 @RestController 61 @RestController
@@ -601,14 +602,35 @@ public class ProductController { @@ -601,14 +602,35 @@ public class ProductController {
601 private void clearBatchProductCache(List<Integer> skupList) { 602 private void clearBatchProductCache(List<Integer> skupList) {
602 try { 603 try {
603 LOG.info("in clearBatchProductCache skupList = {}", skupList); 604 LOG.info("in clearBatchProductCache skupList = {}", skupList);
604 - List<StoragePrice> spList = productService.getStoragePriceBySkupList(skupList);  
605 - List<Integer> productIdList = spList.stream().map(StoragePrice::getProductId).distinct().collect(Collectors.toList());  
606 - List<Integer> storageIdList = spList.stream().map(StoragePrice::getStorageId).distinct().collect(Collectors.toList()); 605 + List<StoragePrice> storagePriceList = productService.getStoragePriceBySkupList(skupList);
  606 + List<Integer> productIdList = storagePriceList.stream().map(StoragePrice::getProductId).distinct().collect(Collectors.toList());
  607 + List<Integer> storageIdList = storagePriceList.stream().map(StoragePrice::getStorageId).distinct().collect(Collectors.toList());
607 if (CollectionUtils.isNotEmpty(productIdList)) { 608 if (CollectionUtils.isNotEmpty(productIdList)) {
608 for (Integer productId : productIdList) { 609 for (Integer productId : productIdList) {
609 LOG.info("Batch clearCache queryProductDetailById productId = {}, ", productId); 610 LOG.info("Batch clearCache queryProductDetailById productId = {}, ", productId);
610 611
611 - storagePriceService.publishPriceUpdateEvent(productId); 612 + storagePriceService.publishPriceUpdateEventIf(productId, oldPrices -> {
  613 + // 缓存不存在,需要更新
  614 + if (CollectionUtils.isEmpty(oldPrices)) {
  615 + return true;
  616 + }
  617 + // 比最低价要低,需要更新
  618 + if(storagePriceList.stream()
  619 + .filter(e -> Objects.equals(e.getProductId(), productId))
  620 + .anyMatch(newPrice -> oldPrices.stream()
  621 + .filter(oldPrice -> Objects.equals(newPrice.getStorageId(), oldPrice.getStorageId()))
  622 + .anyMatch(oldPrice -> newPrice.getPrice().compareTo(oldPrice.getPrice()) < 0))){
  623 + return true;
  624 + }
  625 + // 如果当前skup为缓存中商品,需要更新
  626 + if(storagePriceList.stream()
  627 + .filter(e -> Objects.equals(e.getProductId(), productId))
  628 + .anyMatch(newPrice -> oldPrices.stream()
  629 + .anyMatch(oldPrice -> Objects.equals(newPrice.getSkup(), oldPrice.getSkup())))){
  630 + return true;
  631 + }
  632 + return false;
  633 + });
612 634
613 //商品详情 635 //商品详情
614 cacheAop.clearCache( 636 cacheAop.clearCache(
@@ -659,7 +681,7 @@ public class ProductController { @@ -659,7 +681,7 @@ public class ProductController {
659 } 681 }
660 } 682 }
661 Map<String, StoragePrice> distinctStorage = new HashMap<>(); 683 Map<String, StoragePrice> distinctStorage = new HashMap<>();
662 - for(StoragePrice sp : spList) { 684 + for(StoragePrice sp : storagePriceList) {
663 Integer skup = sp.getSkup(); 685 Integer skup = sp.getSkup();
664 Integer storageId = sp.getStorageId(); 686 Integer storageId = sp.getStorageId();
665 if (sp.getPreSaleFlag() != null && (sp.getPreSaleFlag() == 5 || sp.getPreSaleFlag() == 6)) { 687 if (sp.getPreSaleFlag() != null && (sp.getPreSaleFlag() == 5 || sp.getPreSaleFlag() == 6)) {
@@ -13,11 +13,11 @@ import org.slf4j.Logger; @@ -13,11 +13,11 @@ import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory; 13 import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Autowired; 14 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
16 -import org.springframework.web.bind.annotation.RequestParam;  
17 16
18 import java.util.List; 17 import java.util.List;
19 import java.util.Map; 18 import java.util.Map;
20 import java.util.function.Function; 19 import java.util.function.Function;
  20 +import java.util.function.Predicate;
21 import java.util.stream.Collectors; 21 import java.util.stream.Collectors;
22 22
23 /** 23 /**
@@ -97,6 +97,13 @@ public class StoragePriceService { @@ -97,6 +97,13 @@ public class StoragePriceService {
97 return true; 97 return true;
98 } 98 }
99 99
  100 + public void publishPriceUpdateEventIf(Integer productId, Predicate<List<StoragePrice>> predicate) {
  101 + List<StoragePrice> sizePriceCacheList = productCacheService.getListCacheByString(UfoProductCacheKeyEnum.STORAGE_PRICE_IN_STOCK_INFO_KEY, StoragePrice.class, productId);
  102 + if (predicate.test(sizePriceCacheList)) {
  103 + publishPriceUpdateEvent(productId);
  104 + }
  105 + }
  106 +
100 public void publishPriceUpdateEvent(Integer productId) { 107 public void publishPriceUpdateEvent(Integer productId) {
101 LOGGER.info("method com.yohoufo.product.service.impl.StoragePriceService.publishPriceUpdateEvent in productId is 【{}】", productId); 108 LOGGER.info("method com.yohoufo.product.service.impl.StoragePriceService.publishPriceUpdateEvent in productId is 【{}】", productId);
102 109
  1 +package com.yohoufo.product.util;
  2 +
  3 +import java.util.concurrent.*;
  4 +import java.util.concurrent.atomic.AtomicInteger;
  5 +
  6 +public class ThreadPoolFactory {
  7 +
  8 + private final static ExecutorService cacheCleanExecutorService;
  9 +
  10 + static {
  11 + int numberOfProcessorsAvailable = Runtime.getRuntime().availableProcessors();
  12 + cacheCleanExecutorService = new ThreadPoolExecutor(
  13 + numberOfProcessorsAvailable,
  14 + numberOfProcessorsAvailable * 2,
  15 + 60, TimeUnit.SECONDS,
  16 + new ArrayBlockingQueue<>(100),
  17 + NamedThreadFactory.newThreadFactory("cache-clean"),
  18 + new ThreadPoolExecutor.CallerRunsPolicy()
  19 + );
  20 + }
  21 +
  22 +
  23 + public static ExecutorService cacheCleanExecutorService() {
  24 + return cacheCleanExecutorService;
  25 + }
  26 +
  27 +
  28 + public static class NamedThreadFactory implements ThreadFactory {
  29 +
  30 + private static final AtomicInteger poolNumber = new AtomicInteger(1);
  31 + private final AtomicInteger threadNumber = new AtomicInteger(1);
  32 + private final String namePrefix;
  33 + private final ThreadGroup group;
  34 +
  35 + public static ThreadFactory newThreadFactory(String bizName) {
  36 + return new NamedThreadFactory(bizName);
  37 + }
  38 +
  39 + private NamedThreadFactory(String bizName) {
  40 + SecurityManager s = System.getSecurityManager();
  41 + group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
  42 + namePrefix = "product-pool-" + bizName + "-processor-" + poolNumber.getAndIncrement() + "-thread-";
  43 + }
  44 +
  45 + @Override
  46 + public Thread newThread(Runnable r) {
  47 + Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
  48 + if (t.isDaemon())
  49 + t.setDaemon(true);
  50 + if (t.getPriority() != Thread.NORM_PRIORITY)
  51 + t.setPriority(Thread.NORM_PRIORITY);
  52 + return t;
  53 + }
  54 + }
  55 +
  56 +
  57 +}