123 lines
3.6 KiB
PHP
123 lines
3.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace MageSail\Magesail\Model;
|
|
|
|
use Magento\Framework\App\Config\ScopeConfigInterface;
|
|
use Magento\Framework\App\Filesystem\DirectoryList;
|
|
use Magento\Framework\Shell;
|
|
|
|
/**
|
|
* Single source of truth for tunnel PID/key state and process checks.
|
|
*/
|
|
class TunnelStatus
|
|
{
|
|
private const XML_AUTO_RESTART = 'magesail/settings/auto_restart';
|
|
|
|
public function __construct(
|
|
private readonly Shell $shell,
|
|
private readonly DirectoryList $directoryList,
|
|
private readonly ScopeConfigInterface $scopeConfig,
|
|
private readonly TunnelStoreProvisioner $tunnelStoreProvisioner
|
|
) {
|
|
}
|
|
|
|
public function getPidFilePath(): string
|
|
{
|
|
return $this->directoryList->getPath(DirectoryList::VAR_DIR) . '/magesail.pid';
|
|
}
|
|
|
|
public function getKeyFilePath(): string
|
|
{
|
|
return $this->directoryList->getPath(DirectoryList::VAR_DIR) . '/magesail.key';
|
|
}
|
|
|
|
public function getLogFilePath(): string
|
|
{
|
|
return $this->directoryList->getPath(DirectoryList::VAR_DIR) . '/log/magesail_tunnel.log';
|
|
}
|
|
|
|
/**
|
|
* @return array{running: bool, pid: int|null, key: string|null}
|
|
*/
|
|
public function getStatus(): array
|
|
{
|
|
$pidFile = $this->getPidFilePath();
|
|
$keyFile = $this->getKeyFilePath();
|
|
if (!\is_file($pidFile)) {
|
|
return ['running' => false, 'pid' => null, 'key' => null];
|
|
}
|
|
$pid = (int) trim((string) file_get_contents($pidFile));
|
|
if ($pid <= 0) {
|
|
return ['running' => false, 'pid' => null, 'key' => null];
|
|
}
|
|
if (!$this->isProcessAlive($pid)) {
|
|
$this->maybeTeardownTunnelStoreForStaleProcess();
|
|
@unlink($pidFile);
|
|
$kf = $this->getKeyFilePath();
|
|
if (\is_file($kf)) {
|
|
@unlink($kf);
|
|
}
|
|
return ['running' => false, 'pid' => null, 'key' => null];
|
|
}
|
|
$key = null;
|
|
if (\is_file($keyFile)) {
|
|
$key = trim((string) file_get_contents($keyFile));
|
|
if ($key === '') {
|
|
$key = null;
|
|
}
|
|
}
|
|
return ['running' => true, 'pid' => $pid, 'key' => $key];
|
|
}
|
|
|
|
public function isRunning(): bool
|
|
{
|
|
return $this->getStatus()['running'];
|
|
}
|
|
|
|
public function isProcessAlive(int $pid): bool
|
|
{
|
|
if ($pid <= 0) {
|
|
return false;
|
|
}
|
|
try {
|
|
$this->shell->execute("ps -p %s > /dev/null 2>&1", [$pid]);
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If PID file exists but process is dead, remove pid/key files.
|
|
*/
|
|
public function cleanupStaleState(): void
|
|
{
|
|
$pidFile = $this->getPidFilePath();
|
|
if (!\is_file($pidFile)) {
|
|
return;
|
|
}
|
|
$pid = (int) trim((string) file_get_contents($pidFile));
|
|
if ($pid <= 0 || !$this->isProcessAlive($pid)) {
|
|
$this->maybeTeardownTunnelStoreForStaleProcess();
|
|
@unlink($pidFile);
|
|
$keyFile = $this->getKeyFilePath();
|
|
if (\is_file($keyFile)) {
|
|
@unlink($keyFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* When the tunnel process is gone and auto-restart is off, remove the tunnel store view.
|
|
*/
|
|
private function maybeTeardownTunnelStoreForStaleProcess(): void
|
|
{
|
|
$autoRestart = (bool) $this->scopeConfig->getValue(self::XML_AUTO_RESTART);
|
|
if ($autoRestart) {
|
|
return;
|
|
}
|
|
$this->tunnelStoreProvisioner->teardownAfterStaleProcess();
|
|
}
|
|
}
|