Manager.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <?php
  2. namespace think\swoole\queue;
  3. use Closure;
  4. use Swoole\Constant;
  5. use Swoole\Process;
  6. use Swoole\Process\Pool;
  7. use Swoole\Server;
  8. use Swoole\Timer;
  9. use think\helper\Arr;
  10. use think\queue\event\JobFailed;
  11. use think\queue\Worker;
  12. use think\swoole\concerns\InteractsWithRpcClient;
  13. use think\swoole\concerns\WithContainer;
  14. use function Swoole\Coroutine\run;
  15. class Manager
  16. {
  17. use WithContainer, InteractsWithRpcClient;
  18. /**
  19. * @var Closure[]
  20. */
  21. protected $workers = [];
  22. public function attachToServer(Server $server)
  23. {
  24. $this->listenForEvents();
  25. $this->createWorkers();
  26. foreach ($this->workers as $worker) {
  27. $server->addProcess(new Process($worker, false, 0, true));
  28. }
  29. }
  30. public function run(): void
  31. {
  32. @cli_set_process_title('swoole queue: manager process');
  33. $this->listenForEvents();
  34. $this->createWorkers();
  35. $pool = new Pool(count($this->workers));
  36. $pool->on(Constant::EVENT_WORKER_START, function (Pool $pool, int $workerId) {
  37. $process = $pool->getProcess($workerId);
  38. run($this->workers[$workerId], $process);
  39. });
  40. $pool->start();
  41. }
  42. protected function getApplication()
  43. {
  44. return $this->container;
  45. }
  46. protected function createWorkers()
  47. {
  48. $workers = $this->getConfig('queue.workers', []);
  49. foreach ($workers as $queue => $options) {
  50. if (strpos($queue, '@') !== false) {
  51. [$queue, $connection] = explode('@', $queue);
  52. } else {
  53. $connection = null;
  54. }
  55. $this->workers[] = function (Process $process) use ($options, $connection, $queue) {
  56. @cli_set_process_title('swoole queue: worker process');
  57. $this->bindRpcInterface();
  58. /** @var Worker $worker */
  59. $worker = $this->container->make(Worker::class);
  60. $delay = Arr::get($options, 'delay', 0);
  61. $sleep = Arr::get($options, 'sleep', 3);
  62. $tries = Arr::get($options, 'tries', 0);
  63. $timeout = Arr::get($options, 'timeout', 60);
  64. $timer = Timer::after($timeout * 1000, function () use ($process) {
  65. $process->exit();
  66. });
  67. $worker->runNextJob($connection, $queue, $delay, $sleep, $tries);
  68. Timer::clear($timer);
  69. };
  70. }
  71. }
  72. protected function createRpcConnector($name)
  73. {
  74. return $this->getConfig("rpc.client.{$name}");
  75. }
  76. /**
  77. * 注册事件
  78. */
  79. protected function listenForEvents()
  80. {
  81. $this->container->event->listen(JobFailed::class, function (JobFailed $event) {
  82. $this->logFailedJob($event);
  83. });
  84. }
  85. /**
  86. * 记录失败任务
  87. * @param JobFailed $event
  88. */
  89. protected function logFailedJob(JobFailed $event)
  90. {
  91. $this->container['queue.failer']->log(
  92. $event->connection,
  93. $event->job->getQueue(),
  94. $event->job->getRawBody(),
  95. $event->exception
  96. );
  97. }
  98. }