setName('assistant-service:work')->setDescription('医助服务持久队列;未知执行结果不自动重试') ->addOption('once', null, Option::VALUE_NONE, '只处理一轮') ->addOption('sleep', null, Option::VALUE_REQUIRED, '空闲轮询间隔秒数', '3'); } protected function execute(Input $input, Output $output): int { $running = true; if (function_exists('pcntl_async_signals')) { pcntl_async_signals(true); pcntl_signal(SIGTERM, static function () use (&$running): void { $running = false; }); pcntl_signal(SIGINT, static function () use (&$running): void { $running = false; }); } $pause = max(1, min(60, (int) $input->getOption('sleep'))); $worker = new AssistantServiceWorker(); try { do { $worked = false; try { $this->heartbeat('working'); $worked = $worker->runOnce(); $this->heartbeat('idle'); if ($worked || $input->getOption('once')) { $output->writeln('ASSISTANT_SERVICE processed=' . ($worked ? '1' : '0')); } } catch (\Throwable $e) { $this->heartbeat('error'); $output->writeln('ASSISTANT_SERVICE storage_or_configuration_error'); try { Db::connect()->close(); } catch (\Throwable $ignored) {} if ($input->getOption('once')) { return 1; } } if (!$input->getOption('once') && $running && !$worked) { sleep($pause); } } while (!$input->getOption('once') && $running); } finally { $this->heartbeat('stopped'); } return 0; } private function heartbeat(string $phase): void { // 心跳存储故障不能改变原消费者生成/提交语义;总览将显示心跳缺失。 try { AssistantServiceAutomation::workerHeartbeat($phase); } catch (\Throwable $ignored) {} } }