1+ <?php declare (strict_types=1 );
2+
3+ namespace Workbunny \WebmanRqueue \Builders ;
4+
5+ use Illuminate \Redis \Connections \Connection ;
6+ use Psr \Log \LoggerInterface ;
7+ use RedisException ;
8+ use support \Log ;
9+ use Workbunny \WebmanRqueue \Builders \Traits \MessageQueueMethod ;
10+ use Workbunny \WebmanRqueue \Exceptions \WebmanRqueueException ;
11+ use Workerman \Timer ;
12+ use Workerman \Worker ;
13+ use function Workbunny \WebmanRqueue \config ;
14+
15+ abstract class CoGroupBuilder extends GroupBuilder
16+ {
17+
18+ /** @inheritDoc */
19+ public function onWorkerStart (Worker $ worker ): void
20+ {
21+ if ($ this ->getConnection ()) {
22+ // del timer
23+ self ::$ _delTimer = Timer::add ($ this ->getTimerInterval (), function () use ($ worker ) {
24+ // auto del
25+ $ this ->del ();
26+ });
27+ // check pending
28+ if (($ pendingTimeout = $ this ->configs ['pending_timeout ' ] ?? 0 ) > 0 ) {
29+ $ this ->setPendingTimer (Timer::add ($ pendingTimeout / 1000 , function () use ($ worker , $ pendingTimeout ) {
30+ // 超时消息自动ack并requeue,消息自动移除
31+ $ this ->claim ($ worker , $ pendingTimeout );
32+ }));
33+ }
34+ while (1 ) {
35+ try {
36+ // consume
37+ $ this ->consume ($ worker , false );
38+ } catch (WebmanRqueueException $ exception ) {
39+ // 错误日志
40+ Log::channel ('plugin.workbunny.webman-rqueue.warning ' )?->warning('Consume exception. ' , [
41+ 'message ' => $ exception ->getMessage (), 'code ' => $ exception ->getCode (),
42+ 'file ' => $ exception ->getFile () . ': ' . $ exception ->getLine (),
43+ 'trace ' => $ exception ->getTrace ()
44+ ]);
45+ // 兼容旧版
46+ $ this ->getLogger ()?->warning('Consume exception. ' , [
47+ 'message ' => $ exception ->getMessage (), 'code ' => $ exception ->getCode ()
48+ ]);
49+ } finally {
50+ // 协程随机出让 5 - 10 ms
51+ $ coInterval = $ this ->configs ['co_interval ' ] ?? [];
52+ Timer::sleep (($ coInterval ? rand ($ coInterval [0 ], $ coInterval [1 ]) : rand (5 , 10 )) / 1000 );
53+ }
54+ }
55+ }
56+ }
57+
58+ /** @inheritDoc */
59+ public static function classContent (string $ namespace , string $ className , bool $ isDelay ): string
60+ {
61+ $ isDelay = $ isDelay ? 'true ' : 'false ' ;
62+ $ name = self ::getName ("$ namespace \\$ className " );
63+ return <<<doc
64+ <?php declare(strict_types=1);
65+
66+ namespace $ namespace;
67+
68+ use Workbunny\WebmanRqueue\Headers;
69+ use Workbunny\WebmanRqueue\Builders\CoGroupBuilder;
70+ use Illuminate\Redis\Connections\Connection;
71+
72+ class $ className extends CoGroupBuilder
73+ {
74+
75+ /** @see QueueBuilder:: \$configs */
76+ protected array \$configs = [
77+ // 默认由类名自动生成
78+ 'queues' => [
79+ ' $ name'
80+ ],
81+ // 默认由类名自动生成
82+ 'group' => ' $ name',
83+ // 是否延迟
84+ 'delayed' => $ isDelay,
85+ // QOS
86+ 'prefetch_count' => 0,
87+ // Queue size
88+ 'queue_size' => 0,
89+ // 消息pending超时,毫秒
90+ 'pending_timeout' => 0,
91+ // 协程随机出让时间间隔,毫秒
92+ 'co_interval' => [5, 10]
93+ ];
94+
95+ /** @var float|null 消费长轮询时长/消费间隔 100ms */
96+ protected ?float \$timerInterval = 100.0;
97+
98+ /** @var string redis配置 */
99+ protected string \$connection = 'default';
100+
101+ /** @inheritDoc */
102+ public function handler(string \$id, array \$value, Connection \$connection): bool
103+ {
104+ \$header = new Headers( \$value['_header']);
105+ \$body = \$value['_body'];
106+ // TODO 请重写消费逻辑
107+ echo "请重写 $ className::handler\\n";
108+ return true;
109+ }
110+ }
111+ doc ;
112+ }
113+ }
0 commit comments