OrderPaidQueueLogic.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. namespace addons\LuckyGroup\common\queue;
  3. use addons\LuckyGroup\common\logic\order\OpenRewardLogic;
  4. use addons\LuckyGroup\common\models\LuckyGroupActivity;
  5. use addons\LuckyGroup\common\models\LuckyGroupGoods;
  6. use common\enums\RabbitMqEnum;
  7. use common\enums\RedisKeyEnum;
  8. use common\enums\StatusEnum;
  9. use common\helpers\LockHelper;
  10. class OrderPaidQueueLogic
  11. {
  12. const ORDER_ENQUEUE_SET = 'lucky_group_order_enqueue_set'; //正在队列中的订单id
  13. /**
  14. * 付款订单入队 : lucky_group_order_activity:1_goods:2
  15. * @param $mall_id
  16. * @param $activity
  17. * @param $goods_id
  18. * @param array $order_ids
  19. * @param array $order_ids
  20. * @return bool
  21. */
  22. public function enqueue($mall_id, $activity, $goods_id, $order_ids)
  23. {
  24. var_dump('幸运拼团订单入队,order_id:' . implode(',', $order_ids));
  25. foreach ($order_ids as $key => $order_id) {
  26. //判断order_id 是否在集合内
  27. if (!\Yii::$app->redis->sadd(self::ORDER_ENQUEUE_SET, $order_id)) {
  28. unset($order_ids[$key]);
  29. }
  30. }
  31. if (empty($order_ids)) return false;
  32. $queue = $this->getQueueName($activity['id'], $goods_id);
  33. \Yii::$app->redis->lpush($queue, ...$order_ids);
  34. $this->trigger_order_paid_job($mall_id, $activity, $goods_id);
  35. return true;
  36. }
  37. /**
  38. * 获取队列名称
  39. * @param $activity_id
  40. * @param $goods_id
  41. * @return string
  42. */
  43. public function getQueueName($activity_id, $goods_id)
  44. {
  45. return 'lucky_group_order_activity:' . $activity_id . '_goods:' . $goods_id;
  46. }
  47. public function trigger_order_paid_job($mall_id, $activity, $goods_id)
  48. {
  49. $activity_id = $activity['id'];
  50. $queue = $this->getQueueName($activity_id, $goods_id);
  51. //查询活动
  52. $group_require_num = $activity['group_num']; //开团需要人数
  53. $virtual_num = $activity['virtual_num']; //活动设置的虚拟人数
  54. //真实开团需要人数
  55. $real_group_require_num = $group_require_num - $virtual_num;
  56. $num = $real_group_require_num < 0 ? $group_require_num : $real_group_require_num;
  57. //获取队列长度
  58. $queue_len = \Yii::$app->redis->llen($queue);
  59. if ($queue_len < $num) return;
  60. //取出 $num 个订单id
  61. $lock_key = $queue . '_lock';
  62. $lock_key = RedisKeyEnum::suffix($lock_key);
  63. $identification = uniqid();
  64. if (LockHelper::lock($lock_key, $identification, 30, 60)) {
  65. $deal_order_ids = \Yii::$app->redis->lrange($queue, -$num, -1);
  66. if (!empty($deal_order_ids)) {
  67. var_dump('幸运拼团订单开奖,开奖订单id:' . implode(',', $deal_order_ids));
  68. \Yii::$app->redis->ltrim($queue, 0, -($num + 1));
  69. LockHelper::uLock($lock_key, $identification);
  70. //添加队列,由消费者去执行对应的逻辑
  71. $data = [
  72. 'mall_id' => $mall_id,
  73. 'activity_id' => $activity_id,
  74. 'goods_id' => $goods_id,
  75. 'order_ids' => $deal_order_ids
  76. ];
  77. \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK_LUCKY_GROUP, RabbitMqEnum::LUCKY_GROUP_QUEUE, $data, OpenRewardLogic::class, 'handleSync');
  78. } else {
  79. LockHelper::uLock($lock_key, $identification);
  80. }
  81. } else {
  82. var_dump('一直抢不到锁');
  83. //todo 重新触发
  84. // $this->trigger_order_paid_job($mall_id, $activity_id, $goods_id);
  85. }
  86. return;
  87. }
  88. /**
  89. * 移除订单id入队标记
  90. * @param array $order_ids
  91. * @return mixed
  92. */
  93. public function delOrderEnqueueFlag($order_ids)
  94. {
  95. foreach ($order_ids as $order_id) {
  96. \Yii::$app->redis->srem(self::ORDER_ENQUEUE_SET, $order_id);
  97. }
  98. return true;
  99. }
  100. //禁用活动
  101. public function trigger_disable_activity($mall_id, $activity_id)
  102. {
  103. $activity = LuckyGroupActivity::findOne(['id' => $activity_id]);
  104. $lucky_group_goods_list = LuckyGroupGoods::lists(['where' => [['activity_id' => $activity_id]]]);
  105. foreach ($lucky_group_goods_list as $item) {
  106. $queue = $this->getQueueName($activity_id, $item['goods_id']);
  107. //查询活动
  108. $group_require_num = $activity['group_num']; //开团需要人数
  109. $virtual_num = $activity['virtual_num']; //活动设置的虚拟人数
  110. //真实开团需要人数
  111. $real_group_require_num = $group_require_num - $virtual_num;
  112. $num = $real_group_require_num < 0 ? $group_require_num : $real_group_require_num;
  113. //获取队列长度
  114. $queue_len = \Yii::$app->redis->llen($queue);
  115. if ($queue_len > $num) continue;
  116. //取出 $num 个订单id
  117. $lock_key = $queue . '_lock';
  118. $lock_key = RedisKeyEnum::suffix($lock_key);
  119. $identification = uniqid();
  120. if (LockHelper::lock($lock_key, $identification, 30, 60)) {
  121. $deal_order_ids = \Yii::$app->redis->lrange($queue, -$queue_len, -1);
  122. if (!empty($deal_order_ids)) {
  123. \Yii::error('幸运拼团活动禁用,id:' . $activity['id']);
  124. \Yii::$app->redis->ltrim($queue, 0, -($queue_len + 1));
  125. LockHelper::uLock($lock_key, $identification);
  126. //添加队列,由消费者去执行对应的逻辑
  127. $data = [
  128. 'mall_id' => $mall_id,
  129. 'activity_id' => $activity_id,
  130. 'goods_id' => $item['goods_id'],
  131. 'order_ids' => $deal_order_ids
  132. ];
  133. \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, $data, OpenRewardLogic::class, 'disableActivity');
  134. } else {
  135. LockHelper::uLock($lock_key, $identification);
  136. }
  137. } else {
  138. \Yii::error('一直抢不到锁');
  139. //todo 重新触发
  140. $this->trigger_disable_activity($mall_id, $activity_id);
  141. }
  142. }
  143. }
  144. public function delActivity($activity_id){
  145. $lucky_group_goods_list = LuckyGroupGoods::lists(['where' => [['activity_id' => $activity_id],['status'=>StatusEnum::ENABLED]]]);
  146. foreach ($lucky_group_goods_list as $item) {
  147. $queue = $this->getQueueName($activity_id, $item['goods_id']);
  148. $queue_len = \Yii::$app->redis->llen($queue);
  149. if($queue_len) return false;
  150. }
  151. return true;
  152. }
  153. }