builder()
+ .id(RandomStringUtils.randomNumeric(11))
+ .timestamp(new Date())
+ .data(sku)
+ .build();
+ }
+
+ @Override
+ public String topic() {
+ return topic;
+ }
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/aggregate/CreateOrderAggregate.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/aggregate/CreateOrderAggregate.java
new file mode 100644
index 0000000000000000000000000000000000000000..4966dfa05c7a7ea223bc8a8d10ba4e95170ad328
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/aggregate/CreateOrderAggregate.java
@@ -0,0 +1,51 @@
+package cn.bugstack.domain.activity.model.aggregate;
+
+import cn.bugstack.domain.activity.model.entity.ActivityAccountEntity;
+import cn.bugstack.domain.activity.model.entity.ActivityOrderEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author zhaoyongfeng
+ * @description 下单聚合对象
+ * @create 2024-03-16 10:32
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class CreateOrderAggregate {
+
+ /**
+ * 用户ID
+ */
+ private String userId;
+
+ /**
+ * 活动ID
+ */
+ private Long activityId;
+
+ /**
+ * 增加;总次数
+ */
+ private Integer totalCount;
+
+ /**
+ * 增加;日次数
+ */
+ private Integer dayCount;
+
+ /**
+ * 增加;月次数
+ */
+ private Integer monthCount;
+
+ /**
+ * 活动订单实体
+ */
+ private ActivityOrderEntity activityOrderEntity;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityAccountEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityAccountEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4b3cc46453c084f9ee89c4ddc45de760a37452a
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityAccountEntity.java
@@ -0,0 +1,59 @@
+package cn.bugstack.domain.activity.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动账户实体对象
+ * @create 2024-03-16 10:43
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActivityAccountEntity {
+
+ /**
+ * 用户ID
+ */
+ private String userId;
+
+ /**
+ * 活动ID
+ */
+ private Long activityId;
+
+ /**
+ * 总次数
+ */
+ private Integer totalCount;
+
+ /**
+ * 总次数-剩余
+ */
+ private Integer totalCountSurplus;
+
+ /**
+ * 日次数
+ */
+ private Integer dayCount;
+
+ /**
+ * 日次数-剩余
+ */
+ private Integer dayCountSurplus;
+
+ /**
+ * 月次数
+ */
+ private Integer monthCount;
+
+ /**
+ * 月次数-剩余
+ */
+ private Integer monthCountSurplus;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityCountEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityCountEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..86d1496608eabd9ec739583bb046e63d220755d0
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityCountEntity.java
@@ -0,0 +1,39 @@
+package cn.bugstack.domain.activity.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动次数实体对象
+ * @create 2024-03-16 11:19
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActivityCountEntity {
+
+ /**
+ * 活动次数编号
+ */
+ private Long activityCountId;
+
+ /**
+ * 总次数
+ */
+ private Integer totalCount;
+
+ /**
+ * 日次数
+ */
+ private Integer dayCount;
+
+ /**
+ * 月次数
+ */
+ private Integer monthCount;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..0144222bb7d82d1a19e9a8149cfd202de4b8b940
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityEntity.java
@@ -0,0 +1,62 @@
+package cn.bugstack.domain.activity.model.entity;
+
+import cn.bugstack.domain.activity.model.valobj.ActivityStateVO;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动实体对象
+ * @create 2024-03-16 11:15
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActivityEntity {
+
+ /**
+ * 活动ID
+ */
+ private Long activityId;
+
+ /**
+ * 活动名称
+ */
+ private String activityName;
+
+ /**
+ * 活动描述
+ */
+ private String activityDesc;
+
+ /**
+ * 开始时间
+ */
+ private Date beginDateTime;
+
+ /**
+ * 结束时间
+ */
+ private Date endDateTime;
+
+ /**
+ * 活动参与次数配置
+ */
+ private Long activityCountId;
+
+ /**
+ * 抽奖策略ID
+ */
+ private Long strategyId;
+
+ /**
+ * 活动状态
+ */
+ private ActivityStateVO state;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityOrderEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityOrderEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..2872a667c3196c6f2068dc9050224565960c9307
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivityOrderEntity.java
@@ -0,0 +1,82 @@
+package cn.bugstack.domain.activity.model.entity;
+
+import cn.bugstack.domain.activity.model.valobj.OrderStateVO;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动参与实体对象
+ * @create 2024-03-16 09:02
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActivityOrderEntity {
+
+ /**
+ * 用户ID
+ */
+ private String userId;
+
+ /**
+ * sku
+ */
+ private Long sku;
+
+ /**
+ * 活动ID
+ */
+ private Long activityId;
+
+ /**
+ * 活动名称
+ */
+ private String activityName;
+
+ /**
+ * 抽奖策略ID
+ */
+ private Long strategyId;
+
+ /**
+ * 订单ID
+ */
+ private String orderId;
+
+ /**
+ * 下单时间
+ */
+ private Date orderTime;
+
+ /**
+ * 总次数
+ */
+ private Integer totalCount;
+
+ /**
+ * 日次数
+ */
+ private Integer dayCount;
+
+ /**
+ * 月次数
+ */
+ private Integer monthCount;
+
+ /**
+ * 订单状态
+ */
+ private OrderStateVO state;
+
+ /**
+ * 业务仿重ID - 外部透传的,确保幂等
+ */
+ private String outBusinessNo;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivitySkuEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivitySkuEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..67a1ede1f6160e11b81cfb9907c536e08e2f5b77
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/ActivitySkuEntity.java
@@ -0,0 +1,30 @@
+package cn.bugstack.domain.activity.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动sku实体对象
+ * @create 2024-03-16 10:29
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActivitySkuEntity {
+
+ /** 商品sku */
+ private Long sku;
+ /** 活动ID */
+ private Long activityId;
+ /** 活动个人参数ID;在这个活动上,一个人可参与多少次活动(总、日、月) */
+ private Long activityCountId;
+ /** 库存总量 */
+ private Integer stockCount;
+ /** 剩余库存 */
+ private Integer stockCountSurplus;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/SkuRechargeEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/SkuRechargeEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec4b575c37a4a8f24d66cbffe6e1f66089bd9052
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/entity/SkuRechargeEntity.java
@@ -0,0 +1,20 @@
+package cn.bugstack.domain.activity.model.entity;
+
+import lombok.Data;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动商品充值实体对象
+ * @create 2024-03-23 09:11
+ */
+@Data
+public class SkuRechargeEntity {
+
+ /** 用户ID */
+ private String userId;
+ /** 商品SKU - activity + activity count */
+ private Long sku;
+ /** 幂等业务单号,外部谁充值谁透传,这样来保证幂等(多次调用也能确保结果唯一,不会多次充值)。 */
+ private String outBusinessNo;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/ActivitySkuStockKeyVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/ActivitySkuStockKeyVO.java
new file mode 100644
index 0000000000000000000000000000000000000000..5289f95e423fd2460984af975703744db005dbb9
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/ActivitySkuStockKeyVO.java
@@ -0,0 +1,24 @@
+package cn.bugstack.domain.activity.model.valobj;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动sku库存 key 值对象
+ * @create 2024-03-30 09:44
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActivitySkuStockKeyVO {
+
+ /** 商品sku */
+ private Long sku;
+ /** 活动ID */
+ private Long activityId;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/ActivityStateVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/ActivityStateVO.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d4d5692cfbc26d1252046908a15df5d06307912
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/ActivityStateVO.java
@@ -0,0 +1,23 @@
+package cn.bugstack.domain.activity.model.valobj;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author zhaoyongfeng
+ * @description 活动状态值对象
+ * @create 2024-03-16 11:16
+ */
+@Getter
+@AllArgsConstructor
+public enum ActivityStateVO {
+
+ create("create", "创建"),
+ open("open", "开启"),
+ close("close", "关闭"),
+ ;
+
+ private final String code;
+ private final String desc;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/OrderStateVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/OrderStateVO.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c3336b33b7353880eff0664beeea1b7d546ba78
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/model/valobj/OrderStateVO.java
@@ -0,0 +1,21 @@
+package cn.bugstack.domain.activity.model.valobj;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+
+/**
+ * @author zhaoyongfeng
+ * @description 订单状态枚举值对象(用于描述对象属性的值,如枚举,不影响数据库操作的对象,无生命周期)
+ * @create 2024-03-16 10:34
+ */
+@Getter
+@AllArgsConstructor
+public enum OrderStateVO {
+
+ completed("completed", "完成");
+
+ private final String code;
+ private final String desc;
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/repository/IActivityRepository.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/repository/IActivityRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4e5f5cdccf9615e95b7f44ffee224b62f9b7c8
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/repository/IActivityRepository.java
@@ -0,0 +1,40 @@
+package cn.bugstack.domain.activity.repository;
+
+import cn.bugstack.domain.activity.model.aggregate.CreateOrderAggregate;
+import cn.bugstack.domain.activity.model.entity.ActivityCountEntity;
+import cn.bugstack.domain.activity.model.entity.ActivityEntity;
+import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
+import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
+
+import java.util.Date;
+
+/*
+ * @return
+ * @author zhaoyongfeng
+ * @description 活动仓储接口
+ *
+ * @param null
+ */
+public interface IActivityRepository {
+ ActivitySkuEntity queryActivitySku(Long sku);
+
+ ActivityEntity queryRaffleActivityByActivityId(Long activityId);
+
+ ActivityCountEntity queryRaffleActivityCountByActivityCountId(Long activityCountId);
+
+ void doSaveOrder(CreateOrderAggregate createOrderAggregate);
+
+ void cacheActivitySkuStockCount(String cacheKey, Integer stockCount);
+
+ boolean subtractionActivitySkuStock(Long sku, String cacheKey, Date endDateTime);
+
+ void activitySkuStockConsumeSendQueue(ActivitySkuStockKeyVO activitySkuStockKeyVO);
+
+ ActivitySkuStockKeyVO takeQueueValue();
+
+ void clearQueueValue();
+
+ void updateActivitySkuStock(Long sku);
+
+ void clearActivitySkuStock(Long sku);
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/AbstractRaffleActivity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/AbstractRaffleActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..1115cec286b490fc42a4d5d941002f792b34de52
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/AbstractRaffleActivity.java
@@ -0,0 +1,60 @@
+package cn.bugstack.domain.activity.service;
+
+import cn.bugstack.domain.activity.model.aggregate.CreateOrderAggregate;
+import cn.bugstack.domain.activity.model.entity.*;
+import cn.bugstack.domain.activity.repository.IActivityRepository;
+import cn.bugstack.domain.activity.service.rule.IActionChain;
+import cn.bugstack.domain.activity.service.rule.factory.DefaultActivityChainFactory;
+import cn.bugstack.types.enums.ResponseCode;
+import cn.bugstack.types.exception.AppException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+/*
+ * @return
+ * @author zhaoyongfeng
+ * @description 抽奖活动抽象类,定义标准的流程
+ *
+ * @param null
+ */
+@Slf4j
+public abstract class AbstractRaffleActivity extends RaffleActivitySupport implements IRaffleOrder{
+ public AbstractRaffleActivity(IActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory) {
+ super(activityRepository, defaultActivityChainFactory);
+ }
+ @Override
+ public String createSkuRechargeOrder(SkuRechargeEntity skuRechargeEntity) {
+ // 1. 参数校验
+ String userId = skuRechargeEntity.getUserId();
+ Long sku = skuRechargeEntity.getSku();
+ String outBusinessNo = skuRechargeEntity.getOutBusinessNo();
+ if (null == sku || StringUtils.isBlank(userId) || StringUtils.isBlank(outBusinessNo)) {
+ throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
+ }
+
+ // 2. 查询基础信息
+ // 2.1 通过sku查询活动信息
+ ActivitySkuEntity activitySkuEntity = queryActivitySku(sku);
+ // 2.2 查询活动信息
+ ActivityEntity activityEntity = queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
+ // 2.3 查询次数信息(用户在活动上可参与的次数)
+ ActivityCountEntity activityCountEntity = queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());
+
+ // 3. 活动动作规则校验 「过滤失败则直接抛异常」
+ IActionChain actionChain = defaultActivityChainFactory.openActionChain();
+ actionChain.action(activitySkuEntity, activityEntity, activityCountEntity);
+
+ // 4. 构建订单聚合对象
+ CreateOrderAggregate createOrderAggregate = buildOrderAggregate(skuRechargeEntity, activitySkuEntity, activityEntity, activityCountEntity);
+
+ // 5. 保存订单
+ doSaveOrder(createOrderAggregate);
+
+ // 6. 返回单号
+ return createOrderAggregate.getActivityOrderEntity().getOrderId();
+ }
+
+ protected abstract CreateOrderAggregate buildOrderAggregate(SkuRechargeEntity skuRechargeEntity, ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity);
+
+ protected abstract void doSaveOrder(CreateOrderAggregate createOrderAggregate);
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/IRaffleOrder.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/IRaffleOrder.java
new file mode 100644
index 0000000000000000000000000000000000000000..4eb18a945dae504489f4367788f6cbb49b5871e5
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/IRaffleOrder.java
@@ -0,0 +1,23 @@
+package cn.bugstack.domain.activity.service;
+
+import cn.bugstack.domain.activity.model.entity.SkuRechargeEntity;
+
+/*
+ * @return
+ * @author zhaoyongfeng
+ * @description 抽奖活动订单接口
+ *
+ * @param null
+ */
+public interface IRaffleOrder {
+ /**
+ * 创建 sku 账户充值订单,给用户增加抽奖次数
+ *
+ * 1. 在【打卡、签到、分享、对话、积分兑换】等行为动作下,创建出活动订单,给用户的活动账户【日、月】充值可用的抽奖次数。
+ * 2. 对于用户可获得的抽奖次数,比如首次进来就有一次,则是依赖于运营配置的动作,在前端页面上。用户点击后,可以获得一次抽奖次数。
+ *
+ * @param skuRechargeEntity 活动商品充值实体对象
+ * @return 活动ID
+ */
+ String createSkuRechargeOrder(SkuRechargeEntity skuRechargeEntity);
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/ISkuStock.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/ISkuStock.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba926c63f22243d1bfd9da2576e065bec1776050
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/ISkuStock.java
@@ -0,0 +1,39 @@
+package cn.bugstack.domain.activity.service;
+
+import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
+
+/*
+ * @return
+ * @author zhaoyongfeng
+ * @description 活动sku库存处理接口
+ *
+ * @param null
+ */
+public interface ISkuStock {
+ /**
+ * 获取活动sku库存消耗队列
+ *
+ * @return 奖品库存Key信息
+ * @throws InterruptedException 异常
+ */
+ ActivitySkuStockKeyVO takeQueueValue() throws InterruptedException;
+
+ /**
+ * 清空队列
+ */
+ void clearQueueValue();
+
+ /**
+ * 延迟队列 + 任务趋势更新活动sku库存
+ *
+ * @param sku 活动商品
+ */
+ void updateActivitySkuStock(Long sku);
+
+ /**
+ * 缓存库存以消耗完毕,清空数据库库存
+ *
+ * @param sku 活动商品
+ */
+ void clearActivitySkuStock(Long sku);
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/RaffleActivityService.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/RaffleActivityService.java
new file mode 100644
index 0000000000000000000000000000000000000000..65d6b0c95052bb49645a1866bb01f1a78a75c707
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/RaffleActivityService.java
@@ -0,0 +1,80 @@
+package cn.bugstack.domain.activity.service;
+
+import cn.bugstack.domain.activity.model.aggregate.CreateOrderAggregate;
+import cn.bugstack.domain.activity.model.entity.*;
+import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
+import cn.bugstack.domain.activity.model.valobj.OrderStateVO;
+import cn.bugstack.domain.activity.repository.IActivityRepository;
+import cn.bugstack.domain.activity.service.rule.factory.DefaultActivityChainFactory;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/*
+ * @return
+ * @author zhaoyongfeng
+ * @description 抽奖活动服务
+ *
+ * @param null
+ */
+@Service
+public class RaffleActivityService extends AbstractRaffleActivity implements ISkuStock{
+ public RaffleActivityService(IActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory) {
+ super(activityRepository, defaultActivityChainFactory);
+ }
+
+ @Override
+ protected CreateOrderAggregate buildOrderAggregate(SkuRechargeEntity skuRechargeEntity, ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity) {
+ // 订单实体对象
+ ActivityOrderEntity activityOrderEntity = new ActivityOrderEntity();
+ activityOrderEntity.setUserId(skuRechargeEntity.getUserId());
+ activityOrderEntity.setSku(skuRechargeEntity.getSku());
+ activityOrderEntity.setActivityId(activityEntity.getActivityId());
+ activityOrderEntity.setActivityName(activityEntity.getActivityName());
+ activityOrderEntity.setStrategyId(activityEntity.getStrategyId());
+ // 公司里一般会有专门的雪花算法UUID服务,我们这里直接生成个12位就可以了。
+ activityOrderEntity.setOrderId(RandomStringUtils.randomNumeric(12));
+ activityOrderEntity.setOrderTime(new Date());
+ activityOrderEntity.setTotalCount(activityCountEntity.getTotalCount());
+ activityOrderEntity.setDayCount(activityCountEntity.getDayCount());
+ activityOrderEntity.setMonthCount(activityCountEntity.getMonthCount());
+ activityOrderEntity.setState(OrderStateVO.completed);
+ activityOrderEntity.setOutBusinessNo(skuRechargeEntity.getOutBusinessNo());
+
+ // 构建聚合对象
+ return CreateOrderAggregate.builder()
+ .userId(skuRechargeEntity.getUserId())
+ .activityId(activitySkuEntity.getActivityId())
+ .totalCount(activityCountEntity.getTotalCount())
+ .dayCount(activityCountEntity.getDayCount())
+ .monthCount(activityCountEntity.getMonthCount())
+ .activityOrderEntity(activityOrderEntity)
+ .build();
+ }
+
+ @Override
+ protected void doSaveOrder(CreateOrderAggregate createOrderAggregate) {
+ activityRepository.doSaveOrder(createOrderAggregate);
+ }
+
+ @Override
+ public ActivitySkuStockKeyVO takeQueueValue() throws InterruptedException {
+ return activityRepository.takeQueueValue();
+ }
+
+ @Override
+ public void clearQueueValue() {
+ activityRepository.clearQueueValue();
+ }
+
+ @Override
+ public void updateActivitySkuStock(Long sku) {
+ activityRepository.updateActivitySkuStock(sku);
+ }
+
+ @Override
+ public void clearActivitySkuStock(Long sku) {
+ activityRepository.clearActivitySkuStock(sku);
+ }
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/RaffleActivitySupport.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/RaffleActivitySupport.java
new file mode 100644
index 0000000000000000000000000000000000000000..e08f154fda83a83310a3cb7b9fd0d76a34f3d483
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/RaffleActivitySupport.java
@@ -0,0 +1,37 @@
+package cn.bugstack.domain.activity.service;
+
+import cn.bugstack.domain.activity.model.entity.ActivityCountEntity;
+import cn.bugstack.domain.activity.model.entity.ActivityEntity;
+import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
+import cn.bugstack.domain.activity.repository.IActivityRepository;
+import cn.bugstack.domain.activity.service.rule.factory.DefaultActivityChainFactory;
+
+/*
+ * @return
+ * @author zhaoyongfeng
+ * @description 抽奖活动的支撑类
+ *
+ * @param null
+ */
+public class RaffleActivitySupport {
+ protected DefaultActivityChainFactory defaultActivityChainFactory;
+
+ protected IActivityRepository activityRepository;
+
+ public RaffleActivitySupport(IActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory) {
+ this.activityRepository = activityRepository;
+ this.defaultActivityChainFactory = defaultActivityChainFactory;
+ }
+
+ public ActivitySkuEntity queryActivitySku(Long sku) {
+ return activityRepository.queryActivitySku(sku);
+ }
+
+ public ActivityEntity queryRaffleActivityByActivityId(Long activityId) {
+ return activityRepository.queryRaffleActivityByActivityId(activityId);
+ }
+
+ public ActivityCountEntity queryRaffleActivityCountByActivityCountId(Long activityCountId) {
+ return activityRepository.queryRaffleActivityCountByActivityCountId(activityCountId);
+ }
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/ActivityArmory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/ActivityArmory.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe1e2825f96216f231fd8c1cc1149b39247afe45
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/ActivityArmory.java
@@ -0,0 +1,53 @@
+package cn.bugstack.domain.activity.service.armory;
+
+import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
+import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
+import cn.bugstack.domain.activity.repository.IActivityRepository;
+import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
+import cn.bugstack.types.common.Constants;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 活动sku预热
+ * @create 2024-03-30 09:12
+ */
+@Slf4j
+@Service
+public class ActivityArmory implements IActivityArmory, IActivityDispatch {
+
+ @Resource
+ private IActivityRepository activityRepository;
+
+ @Override
+ public boolean assembleActivitySku(Long sku) {
+ // 预热活动sku库存
+ ActivitySkuEntity activitySkuEntity = activityRepository.queryActivitySku(sku);
+ cacheActivitySkuStockCount(sku, activitySkuEntity.getStockCount());
+
+ // 预热活动【查询时预热到缓存】
+ activityRepository.queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
+
+ // 预热活动次数【查询时预热到缓存】
+ activityRepository.queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());
+
+ return true;
+ }
+
+ private void cacheActivitySkuStockCount(Long sku, Integer stockCount) {
+ String cacheKey = Constants.RedisKey.ACTIVITY_SKU_STOCK_COUNT_KEY + sku;
+ activityRepository.cacheActivitySkuStockCount(cacheKey, stockCount);
+ }
+
+ @Override
+ public boolean subtractionActivitySkuStock(Long sku, Date endDateTime) {
+ String cacheKey = Constants.RedisKey.ACTIVITY_SKU_STOCK_COUNT_KEY + sku;
+ return activityRepository.subtractionActivitySkuStock(sku, cacheKey, endDateTime);
+ }
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/IActivityArmory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/IActivityArmory.java
new file mode 100644
index 0000000000000000000000000000000000000000..3eca5a9d409d9cbabb9e94ca85fb6432c6fd3d7e
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/IActivityArmory.java
@@ -0,0 +1,12 @@
+package cn.bugstack.domain.activity.service.armory;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 活动装配预热
+ * @create 2024-03-30 09:09
+ */
+public interface IActivityArmory {
+
+ boolean assembleActivitySku(Long sku);
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/IActivityDispatch.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/IActivityDispatch.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0f8c2857355cdd41d8b78c6f6068183a45bb917
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/armory/IActivityDispatch.java
@@ -0,0 +1,23 @@
+package cn.bugstack.domain.activity.service.armory;
+
+import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
+
+import java.util.Date;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 活动调度【扣减库存】
+ * @create 2024-03-30 09:28
+ */
+public interface IActivityDispatch {
+
+ /**
+ * 根据策略ID和奖品ID,扣减奖品缓存库存
+ *
+ * @param sku 互动SKU
+ * @param endDateTime 活动结束时间,根据结束时间设置加锁的key为结束时间
+ * @return 扣减结果
+ */
+ boolean subtractionActivitySkuStock(Long sku, Date endDateTime);
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/AbstractActionChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/AbstractActionChain.java
new file mode 100644
index 0000000000000000000000000000000000000000..e42ba0f4ae289ef8d792717b6ca47d561b6bfb1a
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/AbstractActionChain.java
@@ -0,0 +1,23 @@
+package cn.bugstack.domain.activity.service.rule;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 下单规则责任链抽象类
+ * @create 2024-03-23 10:16
+ */
+public abstract class AbstractActionChain implements IActionChain {
+
+ private IActionChain next;
+
+ @Override
+ public IActionChain next() {
+ return next;
+ }
+
+ @Override
+ public IActionChain appendNext(IActionChain next) {
+ this.next = next;
+ return next;
+ }
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/IActionChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/IActionChain.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5c8878b04c608e1beccc9c53afc28e341dd374f
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/IActionChain.java
@@ -0,0 +1,16 @@
+package cn.bugstack.domain.activity.service.rule;
+
+import cn.bugstack.domain.activity.model.entity.ActivityCountEntity;
+import cn.bugstack.domain.activity.model.entity.ActivityEntity;
+import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 下单规则过滤接口
+ * @create 2024-03-23 09:40
+ */
+public interface IActionChain extends IActionChainArmory {
+
+ boolean action(ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity);
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/IActionChainArmory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/IActionChainArmory.java
new file mode 100644
index 0000000000000000000000000000000000000000..59b964fa00a13bab2b9e7e5f78f65585844e2f1d
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/IActionChainArmory.java
@@ -0,0 +1,14 @@
+package cn.bugstack.domain.activity.service.rule;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description
+ * @create 2024-03-23 10:15
+ */
+public interface IActionChainArmory {
+
+ IActionChain next();
+
+ IActionChain appendNext(IActionChain next);
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/factory/DefaultActivityChainFactory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/factory/DefaultActivityChainFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..32bee0aaa0d8aa3773b4e10f8e85c8c6af52540d
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/factory/DefaultActivityChainFactory.java
@@ -0,0 +1,47 @@
+package cn.bugstack.domain.activity.service.rule.factory;
+
+import cn.bugstack.domain.activity.service.rule.IActionChain;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 责任链工厂
+ * @create 2024-03-23 10:30
+ */
+@Service
+public class DefaultActivityChainFactory {
+
+ private final IActionChain actionChain;
+
+ /**
+ * 1. 通过构造函数注入。
+ * 2. Spring 可以自动注入 IActionChain 接口实现类到 map 对象中,key 就是 bean 的名字。
+ * 3. 活动下单动作的责任链是固定的,所以直接在构造函数中组装即可。
+ */
+ public DefaultActivityChainFactory(Map actionChainGroup) {
+ actionChain = actionChainGroup.get(ActionModel.activity_base_action.code);
+ actionChain.appendNext(actionChainGroup.get(ActionModel.activity_sku_stock_action.getCode()));
+ }
+
+ public IActionChain openActionChain() {
+ return this.actionChain;
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public enum ActionModel {
+
+ activity_base_action("activity_base_action", "活动的库存、时间校验"),
+ activity_sku_stock_action("activity_sku_stock_action", "活动sku库存"),
+ ;
+
+ private final String code;
+ private final String info;
+
+ }
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/impl/ActivityBaseActionChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/impl/ActivityBaseActionChain.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6a99ef23623bedcb5abef4edc165958506f68b3
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/impl/ActivityBaseActionChain.java
@@ -0,0 +1,43 @@
+package cn.bugstack.domain.activity.service.rule.impl;
+
+import cn.bugstack.domain.activity.model.entity.ActivityCountEntity;
+import cn.bugstack.domain.activity.model.entity.ActivityEntity;
+import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
+import cn.bugstack.domain.activity.model.valobj.ActivityStateVO;
+import cn.bugstack.domain.activity.service.rule.AbstractActionChain;
+import cn.bugstack.types.enums.ResponseCode;
+import cn.bugstack.types.exception.AppException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 活动规则过滤【日期、状态】
+ * @create 2024-03-23 10:23
+ */
+@Slf4j
+@Component("activity_base_action")
+public class ActivityBaseActionChain extends AbstractActionChain {
+
+ @Override
+ public boolean action(ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity) {
+ log.info("活动责任链-基础信息【有效期、状态、库存(sku)】校验开始。sku:{} activityId:{}", activitySkuEntity.getSku(), activityEntity.getActivityId());
+ // 校验;活动状态
+ if (!ActivityStateVO.open.equals(activityEntity.getState())) {
+ throw new AppException(ResponseCode.ACTIVITY_STATE_ERROR.getCode(), ResponseCode.ACTIVITY_STATE_ERROR.getInfo());
+ }
+ // 校验;活动日期「开始时间 <- 当前时间 -> 结束时间」
+ Date currentDate = new Date();
+ if (activityEntity.getBeginDateTime().after(currentDate) || activityEntity.getEndDateTime().before(currentDate)) {
+ throw new AppException(ResponseCode.ACTIVITY_DATE_ERROR.getCode(), ResponseCode.ACTIVITY_DATE_ERROR.getInfo());
+ }
+ // 校验;活动sku库存 「剩余库存从缓存获取的」
+ if (activitySkuEntity.getStockCountSurplus() <= 0) {
+ throw new AppException(ResponseCode.ACTIVITY_SKU_STOCK_ERROR.getCode(), ResponseCode.ACTIVITY_SKU_STOCK_ERROR.getInfo());
+ }
+ return next().action(activitySkuEntity, activityEntity, activityCountEntity);
+ }
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/impl/ActivitySkuStockActionChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/impl/ActivitySkuStockActionChain.java
new file mode 100644
index 0000000000000000000000000000000000000000..dccc221ced14261bb0b6e61d5e258574c75244a5
--- /dev/null
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/activity/service/rule/impl/ActivitySkuStockActionChain.java
@@ -0,0 +1,52 @@
+package cn.bugstack.domain.activity.service.rule.impl;
+
+import cn.bugstack.domain.activity.model.entity.ActivityCountEntity;
+import cn.bugstack.domain.activity.model.entity.ActivityEntity;
+import cn.bugstack.domain.activity.model.entity.ActivitySkuEntity;
+import cn.bugstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
+import cn.bugstack.domain.activity.repository.IActivityRepository;
+import cn.bugstack.domain.activity.service.armory.IActivityDispatch;
+import cn.bugstack.domain.activity.service.rule.AbstractActionChain;
+import cn.bugstack.types.enums.ResponseCode;
+import cn.bugstack.types.exception.AppException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 商品库存规则节点
+ * @create 2024-03-23 10:25
+ */
+@Slf4j
+@Component("activity_sku_stock_action")
+public class ActivitySkuStockActionChain extends AbstractActionChain {
+
+ @Resource
+ private IActivityDispatch activityDispatch;
+ @Resource
+ private IActivityRepository activityRepository;
+
+ @Override
+ public boolean action(ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity) {
+ log.info("活动责任链-商品库存处理【有效期、状态、库存(sku)】开始。sku:{} activityId:{}", activitySkuEntity.getSku(), activityEntity.getActivityId());
+ // 扣减库存
+ boolean status = activityDispatch.subtractionActivitySkuStock(activitySkuEntity.getSku(), activityEntity.getEndDateTime());
+ // true;库存扣减成功
+ if (status) {
+ log.info("活动责任链-商品库存处理【有效期、状态、库存(sku)】成功。sku:{} activityId:{}", activitySkuEntity.getSku(), activityEntity.getActivityId());
+
+ // 写入延迟队列,延迟消费更新库存记录
+ activityRepository.activitySkuStockConsumeSendQueue(ActivitySkuStockKeyVO.builder()
+ .sku(activitySkuEntity.getSku())
+ .activityId(activityEntity.getActivityId())
+ .build());
+
+ return true;
+ }
+
+ throw new AppException(ResponseCode.ACTIVITY_SKU_STOCK_ERROR.getCode(), ResponseCode.ACTIVITY_SKU_STOCK_ERROR.getInfo());
+ }
+
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/AwardEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/AwardEntity.java
index 34bd3a37e2bd42b2576387da2c9a453fa094de8a..1e062892c78622bd36e3c84bbc7934cea3dc625c 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/AwardEntity.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/AwardEntity.java
@@ -6,12 +6,10 @@ import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * @ClassName: AwardEntity
- * @Description:
- * @Author: zhaoyongfeng
- * @Date: 2024/11/14 19:37
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略结果实体
+ * @create 2023-12-23 09:13
*/
-
@Data
@Builder
@AllArgsConstructor
@@ -24,4 +22,3 @@ public class AwardEntity {
private Integer awardId;
}
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleAwardEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleAwardEntity.java
index 140c936e1cea3c997e8a964f863463d501be8991..faf572285de9f68936bc0f69cd158a81f99a3240 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleAwardEntity.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleAwardEntity.java
@@ -6,16 +6,16 @@ import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * @ClassName: RaffleAwardEntity
- * @Description: 抽奖奖品实体
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:25
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖奖品实体
+ * @create 2024-01-06 09:20
*/
@Data
+@Builder
@AllArgsConstructor
@NoArgsConstructor
-@Builder
public class RaffleAwardEntity {
+
/** 奖品ID */
private Integer awardId;
/** 奖品配置信息 */
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java
index 800fa1926471f9201013af476da962f10c026101..28cdaaa8c0729eddd263ea2399527618c850fd3f 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java
@@ -4,25 +4,21 @@ import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
-import org.checkerframework.checker.units.qual.A;
/**
- * @ClassName: RaffleFactorEntity
- * @Description: 抽奖因子实体
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:26
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖因子实体
+ * @create 2024-01-06 09:20
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RaffleFactorEntity {
+
/** 用户ID */
private String userId;
/** 策略ID */
private Long strategyId;
- /** 奖品ID */
- private Integer awardId;
-
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java
index 1e2728be6be77d0e0dcf5bb4bbd7560ac32a17c6..c259ee30aa6523f5be4f675edccdbe6c3df04301 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java
@@ -8,16 +8,16 @@ import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
- * @ClassName: StrategyAwardEntity
- * @Description:
- * @Author: zhaoyongfeng
- * @Date: 2024/11/14 19:32
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略奖品实体
+ * @create 2023-12-23 10:48
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StrategyAwardEntity {
+
/** 抽奖策略ID */
private Long strategyId;
/** 抽奖奖品ID - 内部流转使用 */
@@ -35,5 +35,4 @@ public class StrategyAwardEntity {
/** 排序 */
private Integer sort;
-
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyConditionEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyConditionEntity.java
index 1522557d4b30fcba366a793a1f1ddf8b7689f9aa..0dcbc834afe59891b576cadbb19457f981357216 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyConditionEntity.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyConditionEntity.java
@@ -6,16 +6,16 @@ import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * @ClassName: StrategyConditionEntity
- * @Description:
- * @Author: zhaoyongfeng
- * @Date: 2024/11/14 19:37
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略条件实体
+ * @create 2023-12-23 09:10
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StrategyConditionEntity {
+
/** 用户ID */
private String userId;
/** 策略ID */
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java
index 088e9d70e32d71108dcb383e08d18716482cfa11..597a1eefb3c70682976cba7fcec340f328f9f235 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java
@@ -8,10 +8,9 @@ import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
/**
- * @ClassName: StrategyEntity
- * @Description: 策略实体
- * @Author: zhaoyongfeng
- * @Date: 2024/11/15 23:35
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略实体
+ * @create 2023-12-31 15:24
*/
@Data
@Builder
@@ -19,11 +18,17 @@ import org.apache.commons.lang3.StringUtils;
@NoArgsConstructor
public class StrategyEntity {
- /** 抽奖策略ID */
+ /**
+ * 抽奖策略ID
+ */
private Long strategyId;
- /** 抽奖策略描述 */
+ /**
+ * 抽奖策略描述
+ */
private String strategyDesc;
- /** 抽奖规则模型 rule_weight,rule_blacklist */
+ /**
+ * 抽奖规则模型 rule_weight,rule_blacklist
+ */
private String ruleModels;
public String[] ruleModels() {
@@ -35,8 +40,9 @@ public class StrategyEntity {
String[] ruleModels = this.ruleModels();
if (null == ruleModels) return null;
for (String ruleModel : ruleModels) {
- if("rule_weight".equals(ruleModel)) return ruleModel;
+ if ("rule_weight".equals(ruleModel)) return ruleModel;
}
return null;
}
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java
index 3c4cd8afb390284d09d7a61832c441326788507f..9a59933c64df6ed8c776e45e816a6235cc1123b1 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java
@@ -12,10 +12,9 @@ import java.util.List;
import java.util.Map;
/**
- * @ClassName: StrategyRuleEntity
- * @Description: 策略规则实体
- * @Author: zhaoyongfeng
- * @Date: 2024/11/15 23:36
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略规则实体
+ * @create 2023-12-31 15:32
*/
@Data
@Builder
@@ -66,4 +65,5 @@ public class StrategyRuleEntity {
return resultMap;
}
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLimitTypeVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLimitTypeVO.java
index 060641f0a39a122924bff15cb28b9171d4d099c8..73bdf8af8b3b73dabb3cb53eafde8f3eba1a506d 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLimitTypeVO.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLimitTypeVO.java
@@ -4,10 +4,9 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
- * @ClassName: RuleLimitTypeVO
- * @Description: 规则限定枚举值
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:37
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则限定枚举值
+ * @create 2024-01-27 12:27
*/
@Getter
@AllArgsConstructor
@@ -25,4 +24,3 @@ public enum RuleLimitTypeVO {
private final String info;
}
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
index e5bbecb3bf0b14e40d1377ce30ac93541689cc50..ee94bbdb4b91180a7893fe3cdf383aad09bdce47 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
@@ -1,15 +1,12 @@
package cn.bugstack.domain.strategy.model.valobj;
import lombok.AllArgsConstructor;
-import lombok.Builder;
import lombok.Getter;
-import lombok.NoArgsConstructor;
/**
- * @ClassName: RuleLogicCheckTypeVO
- * @Description: 规则过滤校验类型值对象
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:24
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则过滤校验类型值对象
+ * @create 2024-01-06 11:10
*/
@Getter
@AllArgsConstructor
@@ -23,4 +20,3 @@ public enum RuleLogicCheckTypeVO {
private final String info;
}
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java
index 1b4fea6aae301364758ad2828036d313f754b280..1d667be546e5a251749644d75935c3f9472e0373 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java
@@ -1,18 +1,21 @@
package cn.bugstack.domain.strategy.model.valobj;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
/**
- * @ClassName: RuleTreeNodeLineVO
- * @Description: 规则树节点指向线对象。用于衔接 from->to 节点链路关系
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:37
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则树节点指向线对象。用于衔接 from->to 节点链路关系
+ * @create 2024-01-27 10:49
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RuleTreeNodeLineVO {
+
/** 规则树ID */
private String treeId;
/** 规则Key节点 From */
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java
index cdabd606fee3c00a99e146953e45057be3ccac86..401e9e2466c8c23978e93d4d24900d8fabd49d89 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java
@@ -8,10 +8,9 @@ import lombok.NoArgsConstructor;
import java.util.List;
/**
- * @ClassName: RuleTreeNodeVO
- * @Description: 规则树节点对象
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:37
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则树节点对象
+ * @create 2024-01-27 10:48
*/
@Data
@Builder
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java
index 3b849628b8a3d48d2e816daf55deaf29274884f3..a2b8a50ce8e989566eb6fb374663abe02eed52bf 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java
@@ -8,16 +8,16 @@ import lombok.NoArgsConstructor;
import java.util.Map;
/**
- * @ClassName: RuleTreeVO
- * @Description: 规则树对象【注意;不具有唯一ID,不需要改变数据库结果的对象,可以被定义为值对象】
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:37
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则树对象【注意;不具有唯一ID,不需要改变数据库结果的对象,可以被定义为值对象】
+ * @create 2024-01-27 10:45
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RuleTreeVO {
+
/** 规则树ID */
private String treeId;
/** 规则树名称 */
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java
index cf75649bfe1ea05a9b94ceb7695817e79be68cee..e8db651bca0b653854c1f5c9080463b8961951b9 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java
@@ -1,21 +1,21 @@
package cn.bugstack.domain.strategy.model.valobj;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
/**
- * @ClassName: StrategyAwardRuleModelVO
- * @Description: 抽奖策略规则规则值对象;值对象,没有唯一ID,仅限于从数据库查询对象
- * @Author: zhaoyongfeng
- * @Date: 2024/11/21 0:05
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖策略规则规则值对象;值对象,没有唯一ID,仅限于从数据库查询对象
+ * @create 2024-01-13 09:30
*/
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StrategyAwardRuleModelVO {
+
private String ruleModels;
-}
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardStockKeyVO.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardStockKeyVO.java
index f4113ff03add2c0cc61465f176b8db5ee0652ffd..92c90661a42f3e12ef8c267bbf173481b64aac18 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardStockKeyVO.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardStockKeyVO.java
@@ -6,18 +6,19 @@ import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * @ClassName: StrategyAwardStockKeyVO
- * @Description:
- * @Author: zhaoyongfeng
- * @Date: 2024/11/21 13:20
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略奖品库存Key标识值对象
+ * @create 2024-02-09 11:24
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StrategyAwardStockKeyVO {
- //策略ID
+
+ // 策略ID
private Long strategyId;
// 奖品ID
private Integer awardId;
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
index b8e9c4a9c5aca32aabdf9a686e106a834c0ac100..e1fc321f0f00fd39346e98a6e37322f533ece632 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
@@ -10,11 +10,16 @@ import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import java.util.List;
import java.util.Map;
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略服务仓储接口
+ * @create 2023-12-23 09:33
+ */
public interface IStrategyRepository {
List queryStrategyAwardList(Long strategyId);
- void storeStrategyAwardSearchRateTable(String key, int rateRange, Map strategyAwardSearchRateTable);
+ void storeStrategyAwardSearchRateTable(String key, Integer rateRange, Map strategyAwardSearchRateTable);
Integer getStrategyAwardAssemble(String key, Integer rateKey);
@@ -26,35 +31,36 @@ public interface IStrategyRepository {
StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleModel);
- String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel);
String queryStrategyRuleValue(Long strategyId, String ruleModel);
+ String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel);
StrategyAwardRuleModelVO queryStrategyAwardRuleModelVO(Long strategyId, Integer awardId);
+
/**
* 根据规则树ID,查询树结构信息
*
* @param treeId 规则树ID
* @return 树结构信息
*/
-
RuleTreeVO queryRuleTreeVOByTreeId(String treeId);
+
/**
* 缓存奖品库存
*
* @param cacheKey key
* @param awardCount 库存值
*/
-
void cacheStrategyAwardCount(String cacheKey, Integer awardCount);
+
/**
* 缓存key,decr 方式扣减库存
*
* @param cacheKey 缓存Key
* @return 扣减结果
*/
-
Boolean subtractionAwardStock(String cacheKey);
+
/**
* 写入奖品库存消费队列
*
@@ -71,9 +77,17 @@ public interface IStrategyRepository {
* 更新奖品库存消耗
*
* @param strategyId 策略ID
- * @param awardId 奖品ID
+ * @param awardId 奖品ID
*/
void updateStrategyAwardStock(Long strategyId, Integer awardId);
+ /**
+ * 根据策略ID+奖品ID的唯一值组合,查询奖品信息
+ *
+ * @param strategyId 策略ID
+ * @param awardId 奖品ID
+ * @return 奖品信息
+ */
StrategyAwardEntity queryStrategyAwardEntity(Long strategyId, Integer awardId);
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/AbstractRaffleStrategy.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/AbstractRaffleStrategy.java
similarity index 93%
rename from bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/AbstractRaffleStrategy.java
rename to bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/AbstractRaffleStrategy.java
index f571abc9f706a79c73eef539c2fd45c8be9f13bf..171b415f44de22fd290710c1c1e627d4abff93ff 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/AbstractRaffleStrategy.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/AbstractRaffleStrategy.java
@@ -1,4 +1,4 @@
-package cn.bugstack.domain.strategy;
+package cn.bugstack.domain.strategy.service;
import cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity;
import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity;
@@ -13,10 +13,9 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
/**
- * @ClassName: AbstractRaffleStrategy
- * @Description: 抽奖策略抽象类,定义抽奖的标准流程
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:14
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖策略抽象类,定义抽奖的标准流程
+ * @create 2024-01-06 09:26
*/
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy {
@@ -30,6 +29,7 @@ public abstract class AbstractRaffleStrategy implements IRaffleStrategy {
// 抽奖的决策树 -> 负责抽奖中到抽奖后的规则过滤,如抽奖到A奖品ID,之后要做次数的判断和库存的扣减等。
protected final DefaultTreeFactory defaultTreeFactory;
+ // 为什么 Spring 推荐使用构造注入;https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html
public AbstractRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory) {
this.repository = repository;
this.strategyDispatch = strategyDispatch;
@@ -91,4 +91,3 @@ public abstract class AbstractRaffleStrategy implements IRaffleStrategy {
public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId);
}
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleAward.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleAward.java
similarity index 68%
rename from bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleAward.java
rename to bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleAward.java
index c4bad58dbacd0743c6d971309ed63e6f9be2d900..2373e415f1029203b2d5887ba3d6b1f21f2a1547 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleAward.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleAward.java
@@ -1,9 +1,14 @@
-package cn.bugstack.domain.strategy;
+package cn.bugstack.domain.strategy.service;
import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity;
import java.util.List;
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略奖品接口
+ * @create 2024-02-14 16:44
+ */
public interface IRaffleAward {
/**
@@ -13,5 +18,5 @@ public interface IRaffleAward {
* @return 奖品列表
*/
List queryRaffleStrategyAwardList(Long strategyId);
-}
+}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStock.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStock.java
similarity index 72%
rename from bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStock.java
rename to bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStock.java
index ec59857a5b656d87009aa316f27d572457bf1a03..7bdb8e675b99579294ca74ecb41ea80413a0f67b 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStock.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStock.java
@@ -1,8 +1,14 @@
-package cn.bugstack.domain.strategy;
+package cn.bugstack.domain.strategy.service;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖库存相关服务,获取库存消耗队列
+ * @create 2024-02-09 12:17
+ */
public interface IRaffleStock {
+
/**
* 获取奖品库存消耗队列
*
@@ -18,4 +24,5 @@ public interface IRaffleStock {
* @param awardId 奖品ID
*/
void updateStrategyAwardStock(Long strategyId, Integer awardId);
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStrategy.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStrategy.java
similarity index 75%
rename from bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStrategy.java
rename to bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStrategy.java
index c59010ba9a73b7450ce3dde52062a558f941dfae..1a5dcc841ccd93592c205ed71b50cb4d810cbfd9 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStrategy.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStrategy.java
@@ -1,9 +1,13 @@
-package cn.bugstack.domain.strategy;
-
+package cn.bugstack.domain.strategy.service;
import cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity;
import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity;
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖策略接口
+ * @create 2024-01-06 09:19
+ */
public interface IRaffleStrategy {
/**
@@ -15,4 +19,3 @@ public interface IRaffleStrategy {
RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity);
}
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java
index 06cd1d5ad24b682b9597c528c317b4071547c1fa..2bc451b33055f503ba4daf87a76403f3fc036362 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java
@@ -1,10 +1,9 @@
package cn.bugstack.domain.strategy.service.armory;
-/*
- * @return
- * @author zhaoyongfeng
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
* @description 策略装配库(兵工厂),负责初始化策略计算
- *
- * @param null
+ * @create 2023-12-23 09:44
*/
public interface IStrategyArmory {
@@ -16,5 +15,4 @@ public interface IStrategyArmory {
*/
boolean assembleLotteryStrategy(Long strategyId);
-
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java
index 87965c6149c005ba66e2c4f735ee8f1bfcf377dd..3ffab53c960a7c81523d1d26da14c166c33658a2 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java
@@ -1,12 +1,12 @@
package cn.bugstack.domain.strategy.service.armory;
-/*
- * @return
- * @author zhaoyongfeng
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
* @description 策略抽奖调度
- *
- * @param null
+ * @create 2023-12-31 15:15
*/
public interface IStrategyDispatch {
+
/**
* 获取抽奖策略装配的随机结果
*
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmoryDispatch.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmoryDispatch.java
index 740740801cb13b3c8dfabb42a55ec483497dae29..fc64a94e1e507000133e8966d1ab3f9bce9d8cc0 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmoryDispatch.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmoryDispatch.java
@@ -12,19 +12,18 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
-import java.math.RoundingMode;
import java.security.SecureRandom;
import java.util.*;
/**
- * @ClassName: StrategyArmory
- * @Description: 策略装配库(兵工厂),负责初始化策略计算
- * @Author: zhaoyongfeng
- * @Date: 2024/11/14 17:39
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 策略装配库(兵工厂),负责初始化策略计算
+ * @create 2023-12-23 10:02
*/
@Slf4j
@Service
-public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch{
+public class StrategyArmoryDispatch implements IStrategyArmory, IStrategyDispatch {
+
@Resource
private IStrategyRepository repository;
@@ -42,7 +41,6 @@ public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch
cacheStrategyAwardCount(strategyId, awardId, awardCount);
}
-
// 3.1 默认装配配置【全量抽奖概率】
assembleLotteryStrategy(String.valueOf(strategyId), strategyAwardEntities);
@@ -67,6 +65,7 @@ public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch
return true;
}
+
/**
* 计算公式;
* 1. 找到范围内最小的概率值,比如 0.1、0.02、0.003,需要找到的值是 0.003
@@ -74,7 +73,6 @@ public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch
* 3. 那么「概率 * 1000」分别占比100个、20个、3个,总计是123个
* 4. 后续的抽奖就用123作为随机数的范围值,生成的值100个都是0.1概率的奖品、20个是概率0.02的奖品、最后是3个是0.003的奖品。
*/
-
private void assembleLotteryStrategy(String key, List strategyAwardEntities) {
// 1. 获取最小概率值
BigDecimal minAwardRate = strategyAwardEntities.stream()
@@ -105,14 +103,16 @@ public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch
shuffleStrategyAwardSearchRateTable.put(i, strategyAwardSearchRateTables.get(i));
}
-
// 6. 存放到 Redis
repository.storeStrategyAwardSearchRateTable(key, shuffleStrategyAwardSearchRateTable.size(), shuffleStrategyAwardSearchRateTable);
}
+
/**
* 转换计算,只根据小数位来计算。如【0.01返回100】、【0.009返回1000】、【0.0018返回10000】
*/
private double convert(double min) {
+ if(0 == min) return 1D;
+
double current = min;
double max = 1;
while (current < 1) {
@@ -139,7 +139,7 @@ public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch
// 分布式部署下,不一定为当前应用做的策略装配。也就是值不一定会保存到本应用,而是分布式应用,所以需要从 Redis 中获取。
int rateRange = repository.getRateRange(strategyId);
// 通过生成的随机值,获取概率值奖品查找表的结果
- return repository.getStrategyAwardAssemble(String.valueOf(strategyId), new SecureRandom().nextInt(rateRange));
+ return repository.getStrategyAwardAssemble(String.valueOf(strategyId), secureRandom.nextInt(rateRange));
}
@Override
@@ -148,8 +148,6 @@ public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch
return getRandomAwardId(key);
}
-
-
@Override
public Integer getRandomAwardId(String key) {
// 分布式部署下,不一定为当前应用做的策略装配。也就是值不一定会保存到本应用,而是分布式应用,所以需要从 Redis 中获取。
@@ -158,12 +156,10 @@ public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch
return repository.getStrategyAwardAssemble(key, secureRandom.nextInt(rateRange));
}
-
@Override
public Boolean subtractionAwardStock(Long strategyId, Integer awardId) {
String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_KEY + strategyId + Constants.UNDERLINE + awardId;
return repository.subtractionAwardStock(cacheKey);
}
-
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java
index abcbf8b59090a3fb8b00e8dc13a4935598e10ee4..71ff290b584e1aa3ee613deeb8047c6d683ba268 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java
@@ -1,13 +1,13 @@
package cn.bugstack.domain.strategy.service.raffle;
-import cn.bugstack.domain.strategy.AbstractRaffleStrategy;
-import cn.bugstack.domain.strategy.IRaffleAward;
-import cn.bugstack.domain.strategy.IRaffleStock;
import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity;
import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import cn.bugstack.domain.strategy.repository.IStrategyRepository;
+import cn.bugstack.domain.strategy.service.AbstractRaffleStrategy;
+import cn.bugstack.domain.strategy.service.IRaffleAward;
+import cn.bugstack.domain.strategy.service.IRaffleStock;
import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch;
import cn.bugstack.domain.strategy.service.rule.chain.ILogicChain;
import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
@@ -19,10 +19,9 @@ import org.springframework.stereotype.Service;
import java.util.List;
/**
- * @ClassName: DefaultRaffleStrategy
- * @Description: 默认的抽奖策略实现
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:16
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 默认的抽奖策略实现
+ * @create 2024-01-06 11:46
*/
@Slf4j
@Service
@@ -68,5 +67,3 @@ public class DefaultRaffleStrategy extends AbstractRaffleStrategy implements IRa
}
}
-
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/AbstractLogicChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/AbstractLogicChain.java
index f62d31a5a86a93fc533bd327c6cc9060682584df..a64d975a13fdea036f64f126dcc34c15f711bd1f 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/AbstractLogicChain.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/AbstractLogicChain.java
@@ -3,13 +3,12 @@ package cn.bugstack.domain.strategy.service.rule.chain;
import lombok.extern.slf4j.Slf4j;
/**
- * @ClassName: AbstractLogicChain
- * @Description: 抽奖策略责任链,判断走那种抽奖策略。如;默认抽象、权重抽奖、黑名单抽奖
- * @Author: zhaoyongfeng
- * @Date: 2024/11/18 22:03
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖策略责任链,判断走那种抽奖策略。如;默认抽象、权重抽奖、黑名单抽奖
+ * @create 2024-01-20 09:37
*/
@Slf4j
-public abstract class AbstractLogicChain implements ILogicChain {
+public abstract class AbstractLogicChain implements ILogicChain{
private ILogicChain next;
@@ -27,4 +26,3 @@ public abstract class AbstractLogicChain implements ILogicChain {
protected abstract String ruleModel();
}
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java
index 2010c584afc2f1e6b32b07e00fbf0f6ca2362e22..c297e71928c895609dc772747e3adbb51bdea0a3 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java
@@ -2,23 +2,20 @@ package cn.bugstack.domain.strategy.service.rule.chain;
import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
-/*
- * @return
- * @author zhaoyongfeng
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
* @description 抽奖策略规则责任链接口
- *
- * @param null
+ * @create 2024-01-20 09:40
*/
-public interface ILogicChain extends ILogicChainArmory{
+public interface ILogicChain extends ILogicChainArmory, Cloneable {
/**
* 责任链接口
*
* @param userId 用户ID
* @param strategyId 策略ID
- * @return 奖品ID
+ * @return 奖品对象
*/
DefaultChainFactory.StrategyAwardVO logic(String userId, Long strategyId);
-
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChainArmory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChainArmory.java
index 1c00fd75fe1eb41709d1128b7bdf6ec2e632a638..cd70c99f28f792b553a333bc5650c7cfd2471ddc 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChainArmory.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChainArmory.java
@@ -1,12 +1,14 @@
package cn.bugstack.domain.strategy.service.rule.chain;
-/*
- * @return
- * @author zhaoyongfeng
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
* @description 责任链装配
- *
- * @param null
+ * @create 2024-01-20 11:53
*/
public interface ILogicChainArmory {
+
ILogicChain next();
+
ILogicChain appendNext(ILogicChain next);
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java
index ef0cc426eb556d7eff0886806aa79bfd34990d3d..f624e4307b5f118b2a07390e997788fd3a03f7d8 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java
@@ -4,25 +4,31 @@ import cn.bugstack.domain.strategy.model.entity.StrategyEntity;
import cn.bugstack.domain.strategy.repository.IStrategyRepository;
import cn.bugstack.domain.strategy.service.rule.chain.ILogicChain;
import lombok.*;
+import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
+import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
- * @ClassName: DefaultLogicFactory
- * @Description:
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:05
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 工厂
+ * @create 2024-01-20 10:54
*/
@Service
public class DefaultChainFactory {
-
- private final Map logicChainGroup;
+ // 原型模式获取对象
+ private final ApplicationContext applicationContext;
+ // 仓储信息
protected IStrategyRepository repository;
+ // 存放策略链,策略ID -> 责任链
+ private final Map strategyChainGroup;
- public DefaultChainFactory(Map logicChainGroup, IStrategyRepository repository) {
- this.logicChainGroup = logicChainGroup;
+ public DefaultChainFactory(ApplicationContext applicationContext, IStrategyRepository repository) {
+ this.applicationContext = applicationContext;
this.repository = repository;
+ this.strategyChainGroup = new ConcurrentHashMap<>();
}
/**
@@ -32,33 +38,48 @@ public class DefaultChainFactory {
* @return LogicChain
*/
public ILogicChain openLogicChain(Long strategyId) {
+ ILogicChain cacheLogicChain = strategyChainGroup.get(strategyId);
+ if (null != cacheLogicChain) return cacheLogicChain;
+
StrategyEntity strategy = repository.queryStrategyEntityByStrategyId(strategyId);
String[] ruleModels = strategy.ruleModels();
// 如果未配置策略规则,则只装填一个默认责任链
- if (null == ruleModels || 0 == ruleModels.length) return logicChainGroup.get("default");
+ if (null == ruleModels || 0 == ruleModels.length) {
+ ILogicChain ruleDefaultLogicChain = applicationContext.getBean(LogicModel.RULE_DEFAULT.getCode(), ILogicChain.class);
+ // 写入缓存
+ strategyChainGroup.put(strategyId, ruleDefaultLogicChain);
+ return ruleDefaultLogicChain;
+ }
// 按照配置顺序装填用户配置的责任链;rule_blacklist、rule_weight 「注意此数据从Redis缓存中获取,如果更新库表,记得在测试阶段手动处理缓存」
- ILogicChain logicChain = logicChainGroup.get(ruleModels[0]);
+ ILogicChain logicChain = applicationContext.getBean(ruleModels[0], ILogicChain.class);
ILogicChain current = logicChain;
for (int i = 1; i < ruleModels.length; i++) {
- ILogicChain nextChain = logicChainGroup.get(ruleModels[i]);
+ ILogicChain nextChain = applicationContext.getBean(ruleModels[i], ILogicChain.class);
current = current.appendNext(nextChain);
}
// 责任链的最后装填默认责任链
- current.appendNext(logicChainGroup.get("default"));
+ current.appendNext(applicationContext.getBean(LogicModel.RULE_DEFAULT.getCode(), ILogicChain.class));
+ // 写入缓存
+ strategyChainGroup.put(strategyId, logicChain);
return logicChain;
}
+
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class StrategyAwardVO {
- /** 抽奖奖品ID - 内部流转使用 */
+ /**
+ * 抽奖奖品ID - 内部流转使用
+ */
private Integer awardId;
- /** */
+ /**
+ *
+ */
private String logicModel;
}
@@ -76,5 +97,4 @@ public class DefaultChainFactory {
}
-
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java
index e77513bb92745d78d0bfc3014bfefce74bf4f286..52e20021ced55b4d89a3bf1b988be026f6df69d2 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java
@@ -5,19 +5,22 @@ import cn.bugstack.domain.strategy.service.rule.chain.AbstractLogicChain;
import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import cn.bugstack.types.common.Constants;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
- * @ClassName: RuleBackListLogicFilter
- * @Description: 【抽奖前规则】黑名单用户过滤规则
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:07
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 黑名单责任链
+ * @create 2024-01-20 10:23
*/
@Slf4j
@Component("rule_blacklist")
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class BackListLogicChain extends AbstractLogicChain {
+
@Resource
private IStrategyRepository repository;
@@ -40,7 +43,6 @@ public class BackListLogicChain extends AbstractLogicChain {
.logicModel(ruleModel())
.build();
}
-
}
// 过滤其他责任链
@@ -53,6 +55,4 @@ public class BackListLogicChain extends AbstractLogicChain {
return DefaultChainFactory.LogicModel.RULE_BLACKLIST.getCode();
}
-
}
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java
index 2d6d65f87ffb5304e109b9ac19c01a18a20bb2d4..d32dce7530057989abc31f8e97b4861652b281c1 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java
@@ -4,18 +4,20 @@ import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch;
import cn.bugstack.domain.strategy.service.rule.chain.AbstractLogicChain;
import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
- * @ClassName: RuleLockLogicFilter
- * @Description:
- * @Author: zhaoyongfeng
- * @Date: 2024/11/18 20:25
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 默认的责任链「作为最后一个链」
+ * @create 2024-01-20 10:06
*/
@Slf4j
-@Component("default")
+@Component("rule_default")
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DefaultLogicChain extends AbstractLogicChain {
@Resource
@@ -29,7 +31,6 @@ public class DefaultLogicChain extends AbstractLogicChain {
.awardId(awardId)
.logicModel(ruleModel())
.build();
-
}
@Override
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java
index 42c0dba4f41484b044a6088c89b5d9743dfeb076..44f299c1339d79a9a85268ad467510fcd302313d 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java
@@ -6,18 +6,21 @@ import cn.bugstack.domain.strategy.service.rule.chain.AbstractLogicChain;
import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import cn.bugstack.types.common.Constants;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
+
import javax.annotation.Resource;
import java.util.*;
/**
- * @ClassName: RuleWeightLogicFilter
- * @Description: 【抽奖前规则】根据抽奖权重返回可抽奖范围KEY
- * @Author: zhaoyongfeng
- * @Date: 2024/11/17 16:08
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 权重抽奖责任链
+ * @create 2024-01-20 10:38
*/
@Slf4j
@Component("rule_weight")
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class RuleWeightLogicChain extends AbstractLogicChain {
@Resource
@@ -29,10 +32,6 @@ public class RuleWeightLogicChain extends AbstractLogicChain {
// 根据用户ID查询用户抽奖消耗的积分值,本章节我们先写死为固定的值。后续需要从数据库中查询。
public Long userScore = 0L;
-
- // 根据用户ID查询用户抽奖消耗的积分值,本章节我们先写死为固定的值。后续需要从数据库中查询。
-
-
/**
* 权重责任链过滤;
* 1. 权重规则格式;4000:102,103,104,105 5000:102,103,104,105,106,107 6000:102,103,104,105,106,107,108,109
@@ -44,9 +43,12 @@ public class RuleWeightLogicChain extends AbstractLogicChain {
String ruleValue = repository.queryStrategyRuleValue(strategyId, ruleModel());
- // 1. 根据用户ID查询用户抽奖消耗的积分值,本章节我们先写死为固定的值。后续需要从数据库中查询。
+ // 1. 解析权重规则值 4000:102,103,104,105 拆解为;4000 -> 4000:102,103,104,105 便于比对判断
Map analyticalValueGroup = getAnalyticalValue(ruleValue);
- if (null == analyticalValueGroup || analyticalValueGroup.isEmpty()) return null;
+ if (null == analyticalValueGroup || analyticalValueGroup.isEmpty()) {
+ log.warn("抽奖责任链-权重告警【策略配置权重,但ruleValue未配置相应值】 userId: {} strategyId: {} ruleModel: {}", userId, strategyId, ruleModel());
+ return next().logic(userId, strategyId);
+ }
// 2. 转换Keys值,并默认排序
List analyticalSortedKeys = new ArrayList<>(analyticalValueGroup.keySet());
@@ -60,7 +62,7 @@ public class RuleWeightLogicChain extends AbstractLogicChain {
* nextValue = analyticalSortedKeyValue;
* }
* }
- *
+ * 星球伙伴 @慢慢来 ID 6267 提供
* Long nextValue = analyticalSortedKeys.stream()
* .filter(key -> userScore >= key)
* .max(Comparator.naturalOrder())
@@ -82,7 +84,6 @@ public class RuleWeightLogicChain extends AbstractLogicChain {
.build();
}
-
// 5. 过滤其他责任链
log.info("抽奖责任链-权重放行 userId: {} strategyId: {} ruleModel: {}", userId, strategyId, ruleModel());
return next().logic(userId, strategyId);
@@ -93,7 +94,6 @@ public class RuleWeightLogicChain extends AbstractLogicChain {
return DefaultChainFactory.LogicModel.RULE_WEIGHT.getCode();
}
-
private Map getAnalyticalValue(String ruleValue) {
String[] ruleValueGroups = ruleValue.split(Constants.SPACE);
Map ruleValueMap = new HashMap<>();
@@ -113,5 +113,3 @@ public class RuleWeightLogicChain extends AbstractLogicChain {
}
}
-
-
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/ILogicTreeNode.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/ILogicTreeNode.java
index 598a309ae24ee1490696ef57e19284d5a99725d6..75c0efe2ad6273858622ecbf3ecc109d2e85970e 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/ILogicTreeNode.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/ILogicTreeNode.java
@@ -2,13 +2,13 @@ package cn.bugstack.domain.strategy.service.rule.tree;
import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
-/*
- * @return
- * @author zhaoyongfeng
- * @description 规则数接口
- *
- * @param null
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则树接口
+ * @create 2024-01-27 11:14
*/
public interface ILogicTreeNode {
+
DefaultTreeFactory.TreeActionEntity logic(String userId, Long strategyId, Integer awardId, String ruleValue);
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java
index d6e2a7c91a4d00d959812a7ee3c314eee321a968..9171a652b147f01f872319240c101295ed2a9575 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java
@@ -5,19 +5,15 @@ import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO;
import cn.bugstack.domain.strategy.service.rule.tree.ILogicTreeNode;
import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;
import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.impl.DecisionTreeEngine;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+import lombok.*;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
- * @ClassName: DefaultTreeFactory
- * @Description: 规则树工厂
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:03
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则树工厂
+ * @create 2024-01-27 11:28
*/
@Service
public class DefaultTreeFactory {
@@ -28,11 +24,12 @@ public class DefaultTreeFactory {
this.logicTreeNodeGroup = logicTreeNodeGroup;
}
- public IDecisionTreeEngine openLogicTree(RuleTreeVO ruleTreeVO){
- return new DecisionTreeEngine(logicTreeNodeGroup,ruleTreeVO);
+ public IDecisionTreeEngine openLogicTree(RuleTreeVO ruleTreeVO) {
+ return new DecisionTreeEngine(logicTreeNodeGroup, ruleTreeVO);
}
+
/**
- * 决策树动作
+ * 决策树个动作实习
*/
@Data
@Builder
@@ -42,6 +39,7 @@ public class DefaultTreeFactory {
private RuleLogicCheckTypeVO ruleLogicCheckType;
private StrategyAwardVO strategyAwardVO;
}
+
@Data
@Builder
@AllArgsConstructor
@@ -53,5 +51,4 @@ public class DefaultTreeFactory {
private String awardRuleValue;
}
-
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java
index e57a5e6ed862bb0a8e6c6b6abd6711f1d61821c4..9598b244b7754a25fd4f40f9190ecc30402d4b63 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java
@@ -2,7 +2,13 @@ package cn.bugstack.domain.strategy.service.rule.tree.factory.engine;
import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则树组合接口
+ * @create 2024-01-27 11:33
+ */
public interface IDecisionTreeEngine {
DefaultTreeFactory.StrategyAwardVO process(String userId, Long strategyId, Integer awardId);
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java
index 04211bb2451db375a1aa8525dd8ce4a513cb6106..a7bd234f8552b9a6d08186e806526b06f4230ff1 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java
@@ -1,9 +1,6 @@
package cn.bugstack.domain.strategy.service.rule.tree.factory.engine.impl;
-import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
-import cn.bugstack.domain.strategy.model.valobj.RuleTreeNodeLineVO;
-import cn.bugstack.domain.strategy.model.valobj.RuleTreeNodeVO;
-import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO;
+import cn.bugstack.domain.strategy.model.valobj.*;
import cn.bugstack.domain.strategy.service.rule.tree.ILogicTreeNode;
import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;
@@ -13,10 +10,9 @@ import java.util.List;
import java.util.Map;
/**
- * @ClassName: DecisionTreeEngine
- * @Description: 决策树引擎
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:22
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 决策树引擎
+ * @create 2024-01-27 11:34
*/
@Slf4j
public class DecisionTreeEngine implements IDecisionTreeEngine {
@@ -44,6 +40,7 @@ public class DecisionTreeEngine implements IDecisionTreeEngine {
// 获取决策节点
ILogicTreeNode logicTreeNode = logicTreeNodeGroup.get(ruleTreeNode.getRuleKey());
String ruleValue = ruleTreeNode.getRuleValue();
+
// 决策节点计算
DefaultTreeFactory.TreeActionEntity logicEntity = logicTreeNode.logic(userId, strategyId, awardId, ruleValue);
RuleLogicCheckTypeVO ruleLogicCheckTypeVO = logicEntity.getRuleLogicCheckType();
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLockLogicTreeNode.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLockLogicTreeNode.java
index e6dca586e1959df9e915b11fc7fd6fe14b6109af..b035cfda0229115875ba821cf545d12f7ec24ec0 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLockLogicTreeNode.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLockLogicTreeNode.java
@@ -1,20 +1,23 @@
package cn.bugstack.domain.strategy.service.rule.tree.impl;
import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
+import cn.bugstack.domain.strategy.repository.IStrategyRepository;
import cn.bugstack.domain.strategy.service.rule.tree.ILogicTreeNode;
import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
+import javax.annotation.Resource;
+
/**
- * @ClassName: RuleLockLogicTreeNode
- * @Description: 次数锁节点
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:16
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 次数锁节点
+ * @create 2024-01-27 11:22
*/
@Slf4j
@Component("rule_lock")
public class RuleLockLogicTreeNode implements ILogicTreeNode {
+
// 用户抽奖次数,后续完成这部分流程开发的时候,从数据库/Redis中读取
private Long userRaffleCount = 10L;
@@ -40,6 +43,6 @@ public class RuleLockLogicTreeNode implements ILogicTreeNode {
return DefaultTreeFactory.TreeActionEntity.builder()
.ruleLogicCheckType(RuleLogicCheckTypeVO.TAKE_OVER)
.build();
-
}
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java
index 68ecea0af4526a4d1177d3dcd0ab13e894560f5e..d538b76c69e8ffb7f73cd394743c1976b4e7f294 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java
@@ -8,14 +8,14 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
- * @ClassName: RuleLuckAwardLogic
- * @Description: 兜底奖励节点
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:16
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 兜底奖励节点
+ * @create 2024-01-27 11:23
*/
@Slf4j
@Component("rule_luck_award")
public class RuleLuckAwardLogicTreeNode implements ILogicTreeNode {
+
@Override
public DefaultTreeFactory.TreeActionEntity logic(String userId, Long strategyId, Integer awardId, String ruleValue) {
log.info("规则过滤-兜底奖品 userId:{} strategyId:{} awardId:{} ruleValue:{}", userId, strategyId, awardId, ruleValue);
@@ -36,6 +36,6 @@ public class RuleLuckAwardLogicTreeNode implements ILogicTreeNode {
.awardRuleValue(awardRuleValue)
.build())
.build();
-
}
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleStockLogicTreeNode.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleStockLogicTreeNode.java
index b44b154816353b65c91757039607a122d8ff44ff..9822443626b78263a416f4ef96696b09777e2dac 100644
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleStockLogicTreeNode.java
+++ b/bigmarket-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleStockLogicTreeNode.java
@@ -12,33 +12,34 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
- * @ClassName: RuleStockLogicTreeNode
- * @Description: 库存扣减节点sda
- * @Author: zhaoyongfeng
- * @Date: 2024/11/20 12:16
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 库存扣减节点
+ * @create 2024-01-27 11:25
*/
@Slf4j
@Component("rule_stock")
public class RuleStockLogicTreeNode implements ILogicTreeNode {
+
@Resource
private IStrategyDispatch strategyDispatch;
@Resource
private IStrategyRepository strategyRepository;
-
@Override
public DefaultTreeFactory.TreeActionEntity logic(String userId, Long strategyId, Integer awardId, String ruleValue) {
log.info("规则过滤-库存扣减 userId:{} strategyId:{} awardId:{}", userId, strategyId, awardId);
// 扣减库存
Boolean status = strategyDispatch.subtractionAwardStock(strategyId, awardId);
// true;库存扣减成功,TAKE_OVER 规则节点接管,返回奖品ID,奖品规则配置
- if(status){
+ if (status) {
log.info("规则过滤-库存扣减-成功 userId:{} strategyId:{} awardId:{}", userId, strategyId, awardId);
+
// 写入延迟队列,延迟消费更新数据库记录。【在trigger的job;UpdateAwardStockJob 下消费队列,更新数据库记录】
strategyRepository.awardStockConsumeSendQueue(StrategyAwardStockKeyVO.builder()
.strategyId(strategyId)
.awardId(awardId)
.build());
+
return DefaultTreeFactory.TreeActionEntity.builder()
.ruleLogicCheckType(RuleLogicCheckTypeVO.TAKE_OVER)
.strategyAwardVO(DefaultTreeFactory.StrategyAwardVO.builder()
@@ -47,11 +48,12 @@ public class RuleStockLogicTreeNode implements ILogicTreeNode {
.build())
.build();
}
+
// 如果库存不足,则直接返回放行
log.warn("规则过滤-库存扣减-告警,库存不足。userId:{} strategyId:{} awardId:{}", userId, strategyId, awardId);
return DefaultTreeFactory.TreeActionEntity.builder()
.ruleLogicCheckType(RuleLogicCheckTypeVO.ALLOW)
.build();
-
}
+
}
diff --git a/bigmarket-domain/src/main/java/cn/bugstack/domain/xxx/model/aggregate/package-info.java b/bigmarket-domain/src/main/java/cn/bugstack/domain/xxx/model/aggregate/package-info.java
deleted file mode 100644
index 370736a7afdc268788b2f8ec1ec9f88bdb8e9a02..0000000000000000000000000000000000000000
--- a/bigmarket-domain/src/main/java/cn/bugstack/domain/xxx/model/aggregate/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * 聚合对象;
- * 1. 聚合实体和值对象
- * 2. 聚合是聚合的对象,和提供基础处理对象的方法。但不建议在聚合中引入仓储和接口来做过大的逻辑。而这些复杂的操作应该放到service中处理
- * 3. 对象名称 XxxAggregate
- */
-package cn.bugstack.domain.xxx.model.aggregate;
\ No newline at end of file
diff --git a/bigmarket-infrastructure/pom.xml b/bigmarket-infrastructure/pom.xml
index 49ea93f6666b1128e7033fe1e29d91c8ee760230..583ccba7443e16100dc627ea98548532740764cd 100644
--- a/bigmarket-infrastructure/pom.xml
+++ b/bigmarket-infrastructure/pom.xml
@@ -22,6 +22,14 @@
org.redisson
redisson-spring-boot-starter