|
13 | 13 | use App\Queue\Data\QueueData; |
14 | 14 | use App\Queue\Data\QueueDataInterface; |
15 | 15 | use App\Util\Log\QueueLog; |
| 16 | +use Hyperf\Collection\Collection; |
16 | 17 | use Hyperf\Context\ApplicationContext; |
17 | 18 | use Hyperf\Contract\StdoutLoggerInterface; |
| 19 | +use Hyperf\Coroutine\Parallel; |
| 20 | +use Hyperf\Engine\Coroutine; |
18 | 21 | use Psr\Container\ContainerExceptionInterface; |
19 | 22 | use Psr\Container\NotFoundExceptionInterface; |
20 | 23 |
|
@@ -64,11 +67,10 @@ public function pop(): bool |
64 | 67 | $timeout = $this->timeout; |
65 | 68 |
|
66 | 69 | $retryInterval = $this->retryInterval; // 消息重试次数 |
67 | | - |
68 | 70 | while (true) { |
69 | 71 | try { |
70 | 72 | $pop = $this->redis->brpop($this->queue_name, $timeout); |
71 | | - if (is_array($pop)) { |
| 73 | + if (empty($pop)) { |
72 | 74 | pcntl_signal_dispatch(); |
73 | 75 | $console->info(sprintf('进程[%s] pid:%s 队列为空,自动退出', cli_get_process_title(), $pid)); |
74 | 76 | break; |
@@ -124,6 +126,93 @@ public function pop(): bool |
124 | 126 | return true; |
125 | 127 | } |
126 | 128 |
|
| 129 | + public function coPop(int $parallel_num = 100): bool |
| 130 | + { |
| 131 | + |
| 132 | + $console = ApplicationContext::getContainer()->get(StdoutLoggerInterface::class); |
| 133 | + $logger = ApplicationContext::getContainer()->get(QueueLog::class); |
| 134 | + |
| 135 | + if ($parallel_num < 1) { |
| 136 | + $console->error(sprintf('队列:%s 并行消费数量不能小于1。当前并行数量为:%s', $this->queue_name, $parallel_num)); |
| 137 | + return false; |
| 138 | + } |
| 139 | + |
| 140 | + $pid = posix_getpid(); |
| 141 | + |
| 142 | + $process_title = $this->queue_name . '-' . $pid; |
| 143 | + cli_set_process_title($process_title); |
| 144 | + |
| 145 | + $timeout = $this->timeout; |
| 146 | + |
| 147 | + $retryInterval = $this->retryInterval; // 消息重试次数 |
| 148 | + |
| 149 | + while ($this->len()) { |
| 150 | + $collections = new Collection(); |
| 151 | + |
| 152 | + while (true) { |
| 153 | + try { |
| 154 | + $pop = $this->redis->brpop($this->queue_name, $timeout); |
| 155 | + if (empty($pop)) { |
| 156 | + break; |
| 157 | + } |
| 158 | + $collections->push($pop[1]); |
| 159 | + } catch (\RedisException $exception) { |
| 160 | + $logger->error(sprintf('队列:%s 连接Redis异常.%s', $this->queue_name, $exception->getMessage())); |
| 161 | + break; |
| 162 | + } |
| 163 | + |
| 164 | + if ($collections->count() >= $parallel_num) { |
| 165 | + break; |
| 166 | + } |
| 167 | + } |
| 168 | + |
| 169 | + $count = $collections->count(); |
| 170 | + |
| 171 | + $console->notice(sprintf('进程[%s] pid:%s 消费数据长度%s', cli_get_process_title(), $pid, $count)); |
| 172 | + if ($count === 0) { |
| 173 | + return true; |
| 174 | + } |
| 175 | + |
| 176 | + $class = $this->getQueueDataClass(); |
| 177 | + |
| 178 | + $parallel = new Parallel($parallel_num); |
| 179 | + |
| 180 | + $that = $this; |
| 181 | + /** |
| 182 | + * @var QueueData $dataObject |
| 183 | + */ |
| 184 | + $collections->each(function ($item) use ($that, $class, $parallel, $logger, $console) { |
| 185 | + /** |
| 186 | + * @var QueueData $dataObject |
| 187 | + */ |
| 188 | + $dataObject = new $class(); |
| 189 | + |
| 190 | + $arr = $dataObject->toArr($item); |
| 191 | + $dataObject->parse($arr); |
| 192 | + |
| 193 | + $parallel->add(function () use ($that, $dataObject, $item, $console) { |
| 194 | + |
| 195 | + $t1 = microtime(true); |
| 196 | + |
| 197 | + $handle = $that->handleQueueData($dataObject); |
| 198 | + if ($handle === false) { |
| 199 | + } |
| 200 | + |
| 201 | + $t2 = microtime(true); |
| 202 | + |
| 203 | + $co_id = Coroutine::id();//当前协程id |
| 204 | + |
| 205 | + $console->info(sprintf('队列:%s 消费数据. data:%s 耗时:%s 秒 co_id:%s', $this->queue_name, json_encode($item, JSON_THROW_ON_ERROR), round($t2 - $t1, 3), $co_id)); |
| 206 | + |
| 207 | + return $co_id; |
| 208 | + }); |
| 209 | + }); |
| 210 | + |
| 211 | + $results = $parallel->wait(); |
| 212 | + } |
| 213 | + return true; |
| 214 | + } |
| 215 | + |
127 | 216 | /** |
128 | 217 | * @throws \RedisException |
129 | 218 | */ |
|
0 commit comments