Compare commits
No commits in common. "93e93f3382e868cb5eeb11c2c468d014074612b7" and "7d6667a3f54df1d4764299145ba5d574fef6860a" have entirely different histories.
93e93f3382
...
7d6667a3f5
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
||||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
|
||||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
|
||||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
|
||||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.suisung.mall.common.service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用服务接口
|
|
||||||
*/
|
|
||||||
public interface CommonService {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 尝试获取分布式锁
|
|
||||||
*
|
|
||||||
* @param lockKey 锁的key
|
|
||||||
* @param expireSeconds 锁过期时间(秒)
|
|
||||||
* @return 锁标识(解锁时需用),加锁失败返回null
|
|
||||||
*/
|
|
||||||
String tryDistributedLock(String lockKey, long expireSeconds);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 释放分布式锁
|
|
||||||
*
|
|
||||||
* @param lockKey 锁的key
|
|
||||||
* @param lockValue 加锁时返回的value,确保只有持有锁的线程能解锁
|
|
||||||
* @return 是否释放成功
|
|
||||||
*/
|
|
||||||
boolean releaseLock(String lockKey, String lockValue);
|
|
||||||
}
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
||||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
|
||||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
|
||||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
|
||||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.suisung.mall.common.service.impl;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class CommonServiceImpl {
|
|
||||||
|
|
||||||
@Lazy
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate redisTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 尝试获取分布式锁
|
|
||||||
* <p>
|
|
||||||
* 使用实例:
|
|
||||||
* String lockKey = "order:123";
|
|
||||||
* long expireSeconds = 10;
|
|
||||||
* String lockValue = commonServiceImpl.tryDistributedLock(lockKey, expireSeconds);
|
|
||||||
* if (lockValue != null) {
|
|
||||||
* try {
|
|
||||||
* // 执行业务逻辑
|
|
||||||
* } finally {
|
|
||||||
* commonServiceImpl.releaseLock(lockKey, lockValue);
|
|
||||||
* }
|
|
||||||
* } else {
|
|
||||||
* // 获取锁失败,做相应处理
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @param lockKey 锁的key
|
|
||||||
* @param expireSeconds 锁过期时间(秒)
|
|
||||||
* @return 锁标识(解锁时需用),加锁失败返回null
|
|
||||||
*/
|
|
||||||
public String tryDistributedLock(String lockKey, long expireSeconds) {
|
|
||||||
String lockValue = UUID.randomUUID().toString();
|
|
||||||
try {
|
|
||||||
Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, expireSeconds, TimeUnit.SECONDS);
|
|
||||||
return Boolean.TRUE.equals(success) ? lockValue : null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 记录异常日志,实际项目可用Logger
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 释放分布式锁
|
|
||||||
*
|
|
||||||
* @param lockKey 锁的key
|
|
||||||
* @param lockValue 加锁时返回的value,确保只有持有锁的线程能解锁
|
|
||||||
* @return 是否释放成功
|
|
||||||
*/
|
|
||||||
public boolean releaseLock(String lockKey, String lockValue) {
|
|
||||||
String luaScript =
|
|
||||||
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
|
|
||||||
" return redis.call('del', KEYS[1]) " +
|
|
||||||
"else " +
|
|
||||||
" return 0 " +
|
|
||||||
"end";
|
|
||||||
try {
|
|
||||||
DefaultRedisScript<Long> script = new DefaultRedisScript<>(luaScript, Long.class);
|
|
||||||
Long result = (Long) redisTemplate.execute(script, Collections.singletonList(lockKey), lockValue);
|
|
||||||
return result != null && result > 0;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("释放分布式锁异常,key={}, error={}", lockKey, e.getMessage(), e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -28,16 +28,6 @@ redis:
|
|||||||
separator: ":"
|
separator: ":"
|
||||||
expire: 3600
|
expire: 3600
|
||||||
|
|
||||||
redisson:
|
|
||||||
address: redis://@redis.host@:@redis.port@
|
|
||||||
database: @redis.database@ # Redis 库索引
|
|
||||||
password: @redis.password@ # Redis 密码
|
|
||||||
connectionPoolSize: 64 # 连接池大小
|
|
||||||
connectionMinimumIdleSize: 10 # 最小空闲连接数
|
|
||||||
idleConnectionTimeout: 10000 # 空闲连接超时时间(毫秒)
|
|
||||||
connectTimeout: 10000 # 连接超时时间(毫秒)
|
|
||||||
timeout: 3000 # 命令等待超时时间(毫秒)
|
|
||||||
|
|
||||||
baidu:
|
baidu:
|
||||||
map:
|
map:
|
||||||
app_id: 116444176
|
app_id: 116444176
|
||||||
|
|||||||
@ -10,12 +10,14 @@ package com.suisung.mall.shop.sync.service;
|
|||||||
|
|
||||||
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONArray;
|
||||||
import com.suisung.mall.common.api.CommonResult;
|
import com.suisung.mall.common.api.CommonResult;
|
||||||
|
import com.suisung.mall.common.modules.sync.StoreDbConfig;
|
||||||
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
||||||
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -39,7 +41,6 @@ public interface SyncThirdDataService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量保存商品记录
|
* 批量保存商品记录
|
||||||
*
|
|
||||||
* @param goodsListJSON
|
* @param goodsListJSON
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -47,7 +48,6 @@ public interface SyncThirdDataService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量保存会员记录
|
* 批量保存会员记录
|
||||||
*
|
|
||||||
* @param memberList
|
* @param memberList
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -55,7 +55,6 @@ public interface SyncThirdDataService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 手动触发同步
|
* 手动触发同步
|
||||||
*
|
|
||||||
* @param storeId
|
* @param storeId
|
||||||
* @param syncType
|
* @param syncType
|
||||||
* @return
|
* @return
|
||||||
@ -63,6 +62,7 @@ public interface SyncThirdDataService {
|
|||||||
CommonResult syncManual(String storeId, Integer syncType);
|
CommonResult syncManual(String storeId, Integer syncType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @param appKey
|
* @param appKey
|
||||||
* @param sign
|
* @param sign
|
||||||
* @param multipartFile
|
* @param multipartFile
|
||||||
@ -72,6 +72,7 @@ public interface SyncThirdDataService {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @param appKey
|
* @param appKey
|
||||||
* @param sign
|
* @param sign
|
||||||
* @param folders
|
* @param folders
|
||||||
@ -82,7 +83,6 @@ public interface SyncThirdDataService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载客户端更新包
|
* 下载客户端更新包
|
||||||
*
|
|
||||||
* @param primaryKey
|
* @param primaryKey
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -90,7 +90,6 @@ public interface SyncThirdDataService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取客户端数据库配置
|
* 获取客户端数据库配置
|
||||||
*
|
|
||||||
* @param appKey
|
* @param appKey
|
||||||
* @param sign
|
* @param sign
|
||||||
* @return
|
* @return
|
||||||
@ -99,7 +98,6 @@ public interface SyncThirdDataService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 同步商品数据库存到客户端
|
* 同步商品数据库存到客户端
|
||||||
*
|
|
||||||
* @param appKey
|
* @param appKey
|
||||||
* @param sign
|
* @param sign
|
||||||
* @return
|
* @return
|
||||||
@ -107,29 +105,14 @@ public interface SyncThirdDataService {
|
|||||||
ThirdApiRes getStoreDataRelease(String appKey, String sign);
|
ThirdApiRes getStoreDataRelease(String appKey, String sign);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存一个或多个商品刚刚变化的库存到 redis hash 缓存
|
* 存储扣减商品到redis
|
||||||
*
|
|
||||||
* @param storeData
|
* @param storeData
|
||||||
*/
|
*/
|
||||||
// void saveStoreRelease(Map<String, Integer> storeData);
|
void saveStoreRealeas(Map storeData);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从 Redis 中获取商品(有变动的)库存数据
|
|
||||||
*
|
*
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Map<String, Integer> getProductStockFromRedis();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下单或支付后,批量累加减商品库存,使用 Redis Hash 的原子自增操作,保证并发安全
|
|
||||||
*
|
|
||||||
* @param stockDeltaMap key 为商品唯一key,value 为库存增降量 例如 {"1234567890123": 100, "1234567890124": 50} 库存数为正负整数,单位可能是个数或重量(克)
|
|
||||||
* 数量为正数时,库存数增加;数量为负数时,库存数减少
|
|
||||||
*/
|
|
||||||
void incrProductStockToRedis(Map<String, Integer> stockDeltaMap);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param appKey
|
* @param appKey
|
||||||
* @param sign
|
* @param sign
|
||||||
* @param folders
|
* @param folders
|
||||||
|
|||||||
@ -9,22 +9,27 @@
|
|||||||
package com.suisung.mall.shop.sync.service.impl;
|
package com.suisung.mall.shop.sync.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.core.util.ZipUtil;
|
import cn.hutool.core.util.ZipUtil;
|
||||||
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONArray;
|
||||||
|
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.qcloud.cos.model.COSObjectSummary;
|
import com.qcloud.cos.model.COSObjectSummary;
|
||||||
import com.suisung.mall.common.api.CommonResult;
|
import com.suisung.mall.common.api.CommonResult;
|
||||||
|
|
||||||
import com.suisung.mall.common.enums.DicEnum;
|
import com.suisung.mall.common.enums.DicEnum;
|
||||||
import com.suisung.mall.common.modules.base.ShopBaseProductBrand;
|
import com.suisung.mall.common.modules.base.ShopBaseProductBrand;
|
||||||
import com.suisung.mall.common.modules.base.ShopBaseProductCategory;
|
import com.suisung.mall.common.modules.base.ShopBaseProductCategory;
|
||||||
|
|
||||||
import com.suisung.mall.common.modules.sixun.SxSyncGoods;
|
import com.suisung.mall.common.modules.sixun.SxSyncGoods;
|
||||||
import com.suisung.mall.common.modules.sixun.SxSyncVip;
|
import com.suisung.mall.common.modules.sixun.SxSyncVip;
|
||||||
import com.suisung.mall.common.modules.sync.StoreDbConfig;
|
import com.suisung.mall.common.modules.sync.StoreDbConfig;
|
||||||
@ -33,7 +38,9 @@ import com.suisung.mall.common.modules.sync.SyncConfig;
|
|||||||
import com.suisung.mall.common.modules.sync.SyncFileLog;
|
import com.suisung.mall.common.modules.sync.SyncFileLog;
|
||||||
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
||||||
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
||||||
|
|
||||||
import com.suisung.mall.common.utils.I18nUtil;
|
import com.suisung.mall.common.utils.I18nUtil;
|
||||||
|
|
||||||
import com.suisung.mall.common.utils.StringUtils;
|
import com.suisung.mall.common.utils.StringUtils;
|
||||||
import com.suisung.mall.core.web.service.RedisService;
|
import com.suisung.mall.core.web.service.RedisService;
|
||||||
import com.suisung.mall.shop.base.service.ShopBaseProductCategoryService;
|
import com.suisung.mall.shop.base.service.ShopBaseProductCategoryService;
|
||||||
@ -53,15 +60,15 @@ import com.suisung.mall.shop.sixun.utils.FileUtils;
|
|||||||
import com.suisung.mall.shop.sync.Utils.ThreadFileUtils;
|
import com.suisung.mall.shop.sync.Utils.ThreadFileUtils;
|
||||||
import com.suisung.mall.shop.sync.keymanage.RedisKey;
|
import com.suisung.mall.shop.sync.keymanage.RedisKey;
|
||||||
import com.suisung.mall.shop.sync.service.*;
|
import com.suisung.mall.shop.sync.service.*;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
@ -69,7 +76,6 @@ import org.springframework.http.ResponseEntity;
|
|||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -79,19 +85,17 @@ import java.nio.file.Paths;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements SyncThirdDataService {
|
public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements SyncThirdDataService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SyncThirdDataServiceImpl.class);
|
private static Logger logger = LoggerFactory.getLogger(SyncThirdDataServiceImpl.class);
|
||||||
private final int limitCnt = 300;
|
private final int limitCnt = 300;
|
||||||
private final AtomicLong threadNum = new AtomicLong(0);
|
|
||||||
@Value("${client.path}")
|
@Value("${client.path}")
|
||||||
public String clientPath;
|
public String clientPath;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -100,12 +104,15 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
private SyncConfigService syncConfigService;
|
private SyncConfigService syncConfigService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SxSyncCategoryService sxSyncCategoryService;
|
private SxSyncCategoryService sxSyncCategoryService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SxSyncGoodsService sxSyncGoodsService;
|
private SxSyncGoodsService sxSyncGoodsService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SxSyncVipService sxSyncVipService;
|
private SxSyncVipService sxSyncVipService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ShopNumberSeqService shopNumberSeqService;
|
private ShopNumberSeqService shopNumberSeqService;
|
||||||
|
private final AtomicLong threadNum=new AtomicLong(0);
|
||||||
@Autowired
|
@Autowired
|
||||||
private SyncFileLogService syncFileLogService;
|
private SyncFileLogService syncFileLogService;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -114,11 +121,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RedisService redisService;
|
private RedisService redisService;
|
||||||
|
|
||||||
@Lazy
|
|
||||||
@Autowired
|
|
||||||
private RedisTemplate redisTemplate;
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private StoreDbConfigService storeDbConfigService;
|
private StoreDbConfigService storeDbConfigService;
|
||||||
|
|
||||||
@ -133,7 +135,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
|
|
||||||
@Value("#{accountBaseConfigService.getConfig('tengxun_default_dir')}")
|
@Value("#{accountBaseConfigService.getConfig('tengxun_default_dir')}")
|
||||||
private String TENGXUN_DEFA;
|
private String TENGXUN_DEFA;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量保存商品的分类
|
* 批量保存商品的分类
|
||||||
*
|
*
|
||||||
@ -381,7 +382,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 同步商品分类
|
* 同步商品分类
|
||||||
*
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public CommonResult syncProductClazz(DataBaseInfo dataBaseInfo,String storeId) {
|
public CommonResult syncProductClazz(DataBaseInfo dataBaseInfo,String storeId) {
|
||||||
@ -414,7 +414,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件上传
|
* 文件上传
|
||||||
*
|
|
||||||
* @param appKey
|
* @param appKey
|
||||||
* @param sign
|
* @param sign
|
||||||
* @param page 分页
|
* @param page 分页
|
||||||
@ -447,7 +446,7 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
String filePath= FileUtils.createFolderAndFileUsingFile(folder,filName);
|
String filePath= FileUtils.createFolderAndFileUsingFile(folder,filName);
|
||||||
Path path = Paths.get(filePath);
|
Path path = Paths.get(filePath);
|
||||||
Files.write(path, bytes);
|
Files.write(path, bytes);
|
||||||
logger.info("path-{},parent-{},filename-{},root-{}", path, path.getParent(), path.getFileName().toString(), path.getRoot());
|
logger.info("path-{},parent-{},filename-{},root-{}",path.toString(),path.getParent(),path.getFileName().toString(),path.getRoot());
|
||||||
// String filaPath=path.toString();
|
// String filaPath=path.toString();
|
||||||
// if(filePath.contains(":")){
|
// if(filePath.contains(":")){
|
||||||
// filePath=filePath.substring(filePath.indexOf(":")+1);
|
// filePath=filePath.substring(filePath.indexOf(":")+1);
|
||||||
@ -467,7 +466,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 多线程处理文件
|
* 多线程处理文件
|
||||||
*
|
|
||||||
* @param appKey
|
* @param appKey
|
||||||
* @param sign
|
* @param sign
|
||||||
* @param syncType
|
* @param syncType
|
||||||
@ -681,7 +679,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
if (StrUtil.isBlank(appKey) || StrUtil.isBlank(sign) ) {
|
if (StrUtil.isBlank(appKey) || StrUtil.isBlank(sign) ) {
|
||||||
return new ThirdApiRes().fail(1003, I18nUtil._("缺少必要参数!"));
|
return new ThirdApiRes().fail(1003, I18nUtil._("缺少必要参数!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验签、appid,必要参数判断
|
// 验签、appid,必要参数判断
|
||||||
SyncApp syncAppO = syncAppService.getOne(new LambdaQueryWrapper<SyncApp>()
|
SyncApp syncAppO = syncAppService.getOne(new LambdaQueryWrapper<SyncApp>()
|
||||||
.select(SyncApp::getApp_key, SyncApp::getApp_secret,SyncApp::getStore_id)
|
.select(SyncApp::getApp_key, SyncApp::getApp_secret,SyncApp::getStore_id)
|
||||||
@ -690,78 +687,28 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
if (syncAppO == null) {
|
if (syncAppO == null) {
|
||||||
return new ThirdApiRes().fail(1001, I18nUtil._("签名有误!"));
|
return new ThirdApiRes().fail(1001, I18nUtil._("签名有误!"));
|
||||||
}
|
}
|
||||||
|
Object obRst= redisService.get(RedisKey.STOREDATARELEASE);//商品库存扣减
|
||||||
// Object obRst = redisService.get(RedisKey.STOREDATARELEASE);//商品库存扣减
|
Map storeDataResultMap=new HashMap();
|
||||||
// Map storeDataResultMap = new HashMap();
|
if(obRst!=null){
|
||||||
// if (obRst != null) {
|
Map resultMap=(Map)obRst;
|
||||||
// Map resultMap = (Map) obRst;
|
Set<Map.Entry> sme= resultMap.entrySet();
|
||||||
// Set<Map.Entry> sme = resultMap.entrySet();
|
storeDataResultMap= sme.stream().filter(m->!(m.getValue().equals((double)0))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||||
// storeDataResultMap = sme.stream().filter(m -> !(m.getValue().equals((double) 0))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
Map<String, Integer> storeDataResultMap = getProductStockFromRedis();
|
|
||||||
|
|
||||||
return new ThirdApiRes().success("success",storeDataResultMap);
|
return new ThirdApiRes().success("success",storeDataResultMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void saveStoreRelease(Map storeData) {
|
|
||||||
// // RMK: 这样写,存在严重的线程安全问题,可能会导致数据丢失或覆盖,
|
|
||||||
// // 改成 redis 原子级别的 hash 类别存储
|
|
||||||
// if (CollectionUtil.isEmpty(storeData)) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// Object obRst = redisService.get(RedisKey.STOREDATARELEASE);
|
|
||||||
// if (obRst != null) {
|
|
||||||
// Map map = (Map) obRst;
|
|
||||||
// map.putAll(storeData);
|
|
||||||
// redisService.set(RedisKey.STOREDATARELEASE, map);
|
|
||||||
// } else {
|
|
||||||
// redisService.set(RedisKey.STOREDATARELEASE, storeData);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Integer> getProductStockFromRedis() {
|
public void saveStoreRealeas(Map storeData) {
|
||||||
try {
|
if(CollectionUtil.isEmpty(storeData)){
|
||||||
// 从 Redis 获取 hash 结构的所有键值对
|
|
||||||
Map<Object, Object> redisHash = redisTemplate.opsForHash().entries(RedisKey.STOREDATARELEASE);
|
|
||||||
if (redisHash == null || redisHash.isEmpty()) {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
// 转换为 Map<String, Integer>
|
|
||||||
return redisHash.entrySet().stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
entry -> String.valueOf(entry.getKey()),
|
|
||||||
entry -> Convert.toInt(entry.getValue(), 0) // 转换失败时默认为 0
|
|
||||||
));
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("从 Redis 获取商品库存失败: {}", e.getMessage(), e);
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void incrProductStockToRedis(Map<String, Integer> stockDeltaMap) {
|
|
||||||
// 校验参数,避免空指针
|
|
||||||
if (CollectionUtil.isEmpty(stockDeltaMap)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Object obRst= redisService.get(RedisKey.STOREDATARELEASE);
|
||||||
for (Map.Entry<String, Integer> entry : stockDeltaMap.entrySet()) {
|
if(obRst!=null){
|
||||||
String productKey = entry.getKey();
|
Map map=(Map)obRst;
|
||||||
Integer delta = entry.getValue();
|
map.putAll(storeData);
|
||||||
if (StrUtil.isBlank(productKey) || delta == null) {
|
redisService.set(RedisKey.STOREDATARELEASE,map);
|
||||||
continue;
|
}else {
|
||||||
}
|
redisService.set(RedisKey.STOREDATARELEASE,storeData);
|
||||||
|
|
||||||
try {
|
|
||||||
// 使用 Redis 的 HINCRBY 保证原子性和高性能
|
|
||||||
redisTemplate.opsForHash().increment(RedisKey.STOREDATARELEASE, productKey, delta);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("库存累加失败,productKey={}, delta={}, error={}", productKey, delta, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -770,7 +717,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
* 压缩商家数据,并上传cos
|
* 压缩商家数据,并上传cos
|
||||||
* 保存商店数据 如
|
* 保存商店数据 如
|
||||||
* "E:\\data\\uploaded\\goods\\2025\\6\\6\\1\\2"
|
* "E:\\data\\uploaded\\goods\\2025\\6\\6\\1\\2"
|
||||||
*
|
|
||||||
* @param path
|
* @param path
|
||||||
*/
|
*/
|
||||||
public void upLoadZipToOss(String path){
|
public void upLoadZipToOss(String path){
|
||||||
@ -798,7 +744,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
* 压缩商家数据,并上传cos
|
* 压缩商家数据,并上传cos
|
||||||
* 保存商店数据 如
|
* 保存商店数据 如
|
||||||
* "E:\\data\\uploaded\\goods\\2025\\6\\6\\1\\2"
|
* "E:\\data\\uploaded\\goods\\2025\\6\\6\\1\\2"
|
||||||
*
|
|
||||||
* @param path
|
* @param path
|
||||||
*/
|
*/
|
||||||
public void dowloadAndUnZip(String path){
|
public void dowloadAndUnZip(String path){
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user