33namespace Utopia \Queue \Adapter ;
44
55use Swoole \Constant ;
6+ use Swoole \Process ;
67use Swoole \Process \Pool ;
7- use Utopia \CLI \Console ;
8+
9+ use Utopia \Console ;
810use Utopia \Queue \Adapter ;
911use Utopia \Queue \Consumer ;
1012
13+ use function Swoole \Coroutine \go ;
14+
1115class Swoole extends Adapter
1216{
1317 protected Pool $ pool ;
1418
15- /** @var callable */
16- private $ onStop ;
17-
18- public function __construct (Consumer $ consumer , int $ workerNum , string $ queue , string $ namespace = 'utopia-queue ' )
19- {
19+ public function __construct (
20+ Consumer $ consumer ,
21+ int $ workerNum ,
22+ string $ queue ,
23+ string $ namespace = "utopia-queue " ,
24+ ) {
2025 parent ::__construct ($ workerNum , $ queue , $ namespace );
2126
2227 $ this ->consumer = $ consumer ;
@@ -25,36 +30,15 @@ public function __construct(Consumer $consumer, int $workerNum, string $queue, s
2530
2631 public function start (): self
2732 {
28- $ this ->pool ->set (['enable_coroutine ' => true ]);
29-
30- // Register signal handlers in the main process before starting pool
31- if (extension_loaded ('pcntl ' )) {
32- pcntl_signal (SIGTERM , function () {
33- Console::info ("[Swoole] Received SIGTERM, initiating graceful shutdown... " );
34- $ this ->stop ();
35- });
36-
37- pcntl_signal (SIGINT , function () {
38- Console::info ("[Swoole] Received SIGINT, initiating graceful shutdown... " );
39- $ this ->stop ();
40- });
41-
42- // Enable async signals
43- pcntl_async_signals (true );
44- } else {
45- Console::warning ("[Swoole] pcntl extension is not loaded, worker will not shutdown gracefully. " );
46- }
33+ // Enable coroutine hooks for Redis and other extensions
34+ $ this ->pool ->set (["enable_coroutine " => true ]);
4735
4836 $ this ->pool ->start ();
4937 return $ this ;
5038 }
5139
5240 public function stop (): self
5341 {
54- if ($ this ->onStop ) {
55- call_user_func ($ this ->onStop );
56- }
57-
5842 Console::info ("[Swoole] Shutting down process pool... " );
5943 $ this ->pool ->shutdown ();
6044 Console::success ("[Swoole] Process pool stopped. " );
@@ -63,33 +47,42 @@ public function stop(): self
6347
6448 public function workerStart (callable $ callback ): self
6549 {
66- $ this ->pool ->on (Constant::EVENT_WORKER_START , function (Pool $ pool , string $ workerId ) use ($ callback ) {
67- // Register signal handlers in each worker process for graceful shutdown
68- if (extension_loaded ('pcntl ' )) {
69- pcntl_signal (SIGTERM , function () use ($ workerId ) {
70- Console::info ("[Worker] Worker {$ workerId } received SIGTERM, closing consumer... " );
71- $ this ->consumer ->close ();
72- });
73-
74- pcntl_signal (SIGINT , function () use ($ workerId ) {
75- Console::info ("[Worker] Worker {$ workerId } received SIGINT, closing consumer... " );
76- $ this ->consumer ->close ();
77- });
78-
79- pcntl_async_signals (true );
80- }
81-
82- call_user_func ($ callback , $ workerId );
50+ $ this ->pool ->on (Constant::EVENT_WORKER_START , function (
51+ Pool $ pool ,
52+ string $ workerId ,
53+ ) use ($ callback ) {
54+ // Register signal handlers for graceful shutdown
55+ Process::signal (SIGTERM , function () use ($ workerId ) {
56+ Console::info (
57+ "[Swoole] Worker {$ workerId } received SIGTERM, stopping consumer... " ,
58+ );
59+ $ this ->consumer ->close ();
60+ });
61+
62+ Process::signal (SIGINT , function () use ($ workerId ) {
63+ Console::info (
64+ "[Swoole] Worker {$ workerId } received SIGINT, stopping consumer... " ,
65+ );
66+ $ this ->consumer ->close ();
67+ });
68+
69+ // Run consume loop in a coroutine to allow event loop to process signals
70+ // The coroutine container waits for all child coroutines before worker exits
71+ go (function () use ($ callback , $ workerId ) {
72+ \call_user_func ($ callback , $ workerId );
73+ });
8374 });
8475
8576 return $ this ;
8677 }
8778
8879 public function workerStop (callable $ callback ): self
8980 {
90- $ this ->onStop = $ callback ;
91- $ this ->pool ->on (Constant::EVENT_WORKER_STOP , function (Pool $ pool , string $ workerId ) use ($ callback ) {
92- call_user_func ($ callback , $ workerId );
81+ $ this ->pool ->on (Constant::EVENT_WORKER_STOP , function (
82+ Pool $ pool ,
83+ string $ workerId ,
84+ ) use ($ callback ) {
85+ \call_user_func ($ callback , $ workerId );
9386 });
9487
9588 return $ this ;
0 commit comments