commands and logs to the database
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Command;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Command\Data\CommandLogItem;
|
||||
|
||||
class CommandRepo
|
||||
{
|
||||
public function findBySignature($signature): ?CommandLogItem
|
||||
{
|
||||
|
||||
$row = DB::table("command_logs")->where("signature", $signature)->first();
|
||||
if (empty($row)) {
|
||||
return null;
|
||||
}
|
||||
return CommandLogItem::fromDB($row);
|
||||
}
|
||||
|
||||
|
||||
public function upsertCommand(CommandLogItem $commandLogItem): void
|
||||
{
|
||||
$foundCommandLogItem = $this->findBySignature($commandLogItem->signature);
|
||||
if (empty($foundCommandLogItem)) {
|
||||
DB::table("command_logs")->insert(toArray($commandLogItem));
|
||||
return;
|
||||
}
|
||||
|
||||
DB::table("command_logs")->where("signature", $commandLogItem->signature)->update(toArray($commandLogItem));
|
||||
}
|
||||
|
||||
public function appendToLogs(string $signature, string $line): void
|
||||
{
|
||||
$res = DB::update(
|
||||
'update command_logs set logs = logs || ? where signature = ?',
|
||||
[$line, $signature]
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Command\Data;
|
||||
|
||||
use stdClass;
|
||||
|
||||
class CommandLogItem
|
||||
{
|
||||
public function __construct(
|
||||
public string $id,
|
||||
public string $signature,
|
||||
public ?int $pid,
|
||||
public string $logs,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public static function fromDB(stdClass $data): self
|
||||
{
|
||||
return new self(
|
||||
id: $data->id,
|
||||
signature: $data->signature,
|
||||
pid: $data->pid,
|
||||
logs: $data->logs,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user