Files
larablog/app/Console/Commands/WorkermanAiCommand.php
T
gouki 3cec4c5e18
CI / PHPUnit (PHP 8.3) (push) Failing after 4s
CI / PHPUnit (PHP 8.2) (push) Failing after 1m9s
CI / Deploy (manual gate) (push) Skipped
wip: article AI polish, category SEO fields, cover generator, membership plan seeder
2026-09-07 18:48:37 +00:00

81 lines
2.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Workerman\Timer;
use Workerman\Worker;
/**
* Long-lived Workerman process for AI queues (content polish + comment moderation).
*
* This is separate from `queue:ai`, which is a short-lived Laravel `queue:work`
* helper for local/dev. Production usually runs either this command OR a
* dedicated `queue:work` on the AI queues — not both.
*/
class WorkermanAiCommand extends Command
{
protected $signature = 'workerman:ai
{action=start : start|stop|restart|reload|status|connections}
{--count=1 : Worker processes}
{--d : Daemonize (pass through to Workerman)}';
protected $description = 'Workerman long-running AI queue consumer (ai-content, ai-moderation). Not started by queue:ai.';
public function handle(): int
{
if (! extension_loaded('pcntl') || ! extension_loaded('posix')) {
$this->error('workerman:ai requires the pcntl and posix PHP extensions (Linux/macOS CLI).');
return self::FAILURE;
}
$action = (string) $this->argument('action');
$allowed = ['start', 'stop', 'restart', 'reload', 'status', 'connections'];
if (! in_array($action, $allowed, true)) {
$this->error('Unknown action. Use: '.implode('|', $allowed));
return self::FAILURE;
}
// Workerman treats `artisan` as the start file, so unset paths default
// to the project root (workerman.log / workerman.artisan.status).
$runtime = storage_path('logs');
if (! is_dir($runtime)) {
mkdir($runtime, 0775, true);
}
Worker::$command = $action.($this->option('d') ? ' -d' : '');
Worker::$pidFile = $runtime.'/workerman-ai.pid';
Worker::$logFile = $runtime.'/workerman-ai.log';
Worker::$statusFile = $runtime.'/workerman-ai.status';
Worker::$stdoutFile = $runtime.'/workerman-ai.stdout.log';
$this->info("Workerman AI: {$action} (queues: ai-content, ai-moderation)");
$worker = new Worker;
$worker->count = max(1, (int) $this->option('count'));
$worker->name = 'larablog-ai';
$worker->onWorkerStart = function () {
Timer::add(1, function () {
Artisan::call('queue:work', [
'--queue' => 'ai-content,ai-moderation',
'--stop-when-empty' => true,
'--max-time' => 50,
'--sleep' => 1,
'--tries' => 3,
]);
});
};
Worker::runAll();
return self::SUCCESS;
}
}