60 lines
1.6 KiB
PHP
60 lines
1.6 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Lucent\Command;
|
||
|
|
|
||
|
|
use Lucent\Command\Data\CommandLogItem;
|
||
|
|
use Lucent\Id\Id;
|
||
|
|
use Lucent\LucentException;
|
||
|
|
use Symfony\Component\Process\PhpExecutableFinder;
|
||
|
|
|
||
|
|
|
||
|
|
class CommandService
|
||
|
|
{
|
||
|
|
|
||
|
|
public function __construct(
|
||
|
|
private CommandRepo $commandRepo,
|
||
|
|
)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
public function run(string $signature): CommandLogItem
|
||
|
|
{
|
||
|
|
$commandLogItem = $this->commandRepo->findBySignature($signature);
|
||
|
|
|
||
|
|
if (empty($commandLogItem)) {
|
||
|
|
$commandLogItem = new CommandLogItem(
|
||
|
|
id: Id::new(),
|
||
|
|
signature: $signature,
|
||
|
|
pid: null,
|
||
|
|
logs: ""
|
||
|
|
);
|
||
|
|
} elseif ($this->commandIsRunning($commandLogItem->pid)) {
|
||
|
|
throw new LucentException('Command is already running');
|
||
|
|
}
|
||
|
|
|
||
|
|
$commandLogItem->pid = $this->runCommand($signature);
|
||
|
|
$commandLogItem->logs = "";
|
||
|
|
$this->commandRepo->upsertCommand($commandLogItem);
|
||
|
|
return $commandLogItem;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function logWriter(string $signature): callable
|
||
|
|
{
|
||
|
|
return function (string $line) use($signature) {
|
||
|
|
$this->commandRepo->appendToLogs($signature, $line.PHP_EOL);
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private function runCommand(string $signature): int
|
||
|
|
{
|
||
|
|
$phpBinaryFinder = new PhpExecutableFinder();
|
||
|
|
$phpBinaryPath = $phpBinaryFinder->find();
|
||
|
|
$pid = (int)shell_exec("cd " . base_path() . " && $phpBinaryPath artisan {$signature} > /dev/null 2>&1 & echo $!");
|
||
|
|
return $pid;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function commandIsRunning(int $pid): bool
|
||
|
|
{
|
||
|
|
return file_exists("/proc/$pid");
|
||
|
|
}
|
||
|
|
}
|