mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-10-27 16:26:32 +01:00
new and improve admin async upgrade process
This commit is contained in:
@@ -870,9 +870,17 @@ class AdminController extends AdminBaseController
|
|||||||
'decisions' => isset($post['decisions']) && is_array($post['decisions']) ? $post['decisions'] : [],
|
'decisions' => isset($post['decisions']) && is_array($post['decisions']) ? $post['decisions'] : [],
|
||||||
];
|
];
|
||||||
|
|
||||||
$result = $this->getSafeUpgradeManager()->run($options);
|
$manager = $this->getSafeUpgradeManager();
|
||||||
|
$result = $manager->queue($options);
|
||||||
$status = $result['status'] ?? 'error';
|
$status = $result['status'] ?? 'error';
|
||||||
|
|
||||||
|
if ($status === 'error') {
|
||||||
|
$manager->clearJobContext();
|
||||||
|
$result = $manager->run($options);
|
||||||
|
$status = $result['status'] ?? 'error';
|
||||||
|
$result['fallback'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
$response = [
|
$response = [
|
||||||
'status' => $status === 'error' ? 'error' : 'success',
|
'status' => $status === 'error' ? 'error' : 'success',
|
||||||
'data' => $result,
|
'data' => $result,
|
||||||
@@ -905,11 +913,21 @@ class AdminController extends AdminBaseController
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$progress = $this->getSafeUpgradeManager()->getProgress();
|
$manager = $this->getSafeUpgradeManager();
|
||||||
|
$jobId = isset($_GET['job']) ? (string)$_GET['job'] : '';
|
||||||
|
|
||||||
|
if ($jobId !== '') {
|
||||||
|
$data = $manager->getJobStatus($jobId);
|
||||||
|
} else {
|
||||||
|
$data = [
|
||||||
|
'job' => null,
|
||||||
|
'progress' => $manager->getProgress(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$this->sendJsonResponse([
|
$this->sendJsonResponse([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'data' => $progress,
|
'data' => $data,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ use Grav\Common\Grav;
|
|||||||
use Grav\Common\HTTP\Response;
|
use Grav\Common\HTTP\Response;
|
||||||
use Grav\Common\Recovery\RecoveryManager;
|
use Grav\Common\Recovery\RecoveryManager;
|
||||||
use Grav\Common\Upgrade\SafeUpgradeService;
|
use Grav\Common\Upgrade\SafeUpgradeService;
|
||||||
|
use Grav\Common\Utils;
|
||||||
use Grav\Installer\Install;
|
use Grav\Installer\Install;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@@ -49,6 +50,8 @@ use const GRAV_SCHEMA;
|
|||||||
class SafeUpgradeManager
|
class SafeUpgradeManager
|
||||||
{
|
{
|
||||||
private const PROGRESS_FILENAME = 'safe-upgrade-progress.json';
|
private const PROGRESS_FILENAME = 'safe-upgrade-progress.json';
|
||||||
|
private const JOB_MANIFEST = 'manifest.json';
|
||||||
|
private const JOB_PROGRESS = 'progress.json';
|
||||||
|
|
||||||
/** @var Grav */
|
/** @var Grav */
|
||||||
private $grav;
|
private $grav;
|
||||||
@@ -59,6 +62,14 @@ class SafeUpgradeManager
|
|||||||
/** @var RecoveryManager */
|
/** @var RecoveryManager */
|
||||||
private $recovery;
|
private $recovery;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
private $progressDir;
|
||||||
|
/** @var string */
|
||||||
|
private $jobsDir;
|
||||||
|
/** @var string|null */
|
||||||
|
private $jobId;
|
||||||
|
/** @var string|null */
|
||||||
|
private $jobManifestPath;
|
||||||
|
/** @var string */
|
||||||
private $progressPath;
|
private $progressPath;
|
||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
private $tmp;
|
private $tmp;
|
||||||
@@ -74,8 +85,247 @@ class SafeUpgradeManager
|
|||||||
$this->recovery = $this->grav['recovery'];
|
$this->recovery = $this->grav['recovery'];
|
||||||
|
|
||||||
$locator = $this->grav['locator'];
|
$locator = $this->grav['locator'];
|
||||||
$progressDir = $locator->findResource('user://data/upgrades', true, true);
|
$this->progressDir = $locator->findResource('user://data/upgrades', true, true);
|
||||||
$this->progressPath = $progressDir . '/' . self::PROGRESS_FILENAME;
|
$this->jobsDir = $this->progressDir . '/jobs';
|
||||||
|
|
||||||
|
Folder::create($this->jobsDir);
|
||||||
|
|
||||||
|
$this->setJobId(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setJobId(?string $jobId): void
|
||||||
|
{
|
||||||
|
$this->jobId = $jobId ?: null;
|
||||||
|
|
||||||
|
if ($this->jobId) {
|
||||||
|
$jobDir = $this->getJobDir($this->jobId);
|
||||||
|
Folder::create($jobDir);
|
||||||
|
$this->jobManifestPath = $jobDir . '/' . self::JOB_MANIFEST;
|
||||||
|
$this->progressPath = $jobDir . '/' . self::JOB_PROGRESS;
|
||||||
|
} else {
|
||||||
|
$this->jobManifestPath = null;
|
||||||
|
$this->progressPath = $this->progressDir . '/' . self::PROGRESS_FILENAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clearJobContext(): void
|
||||||
|
{
|
||||||
|
$this->setJobId(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getJobDir(string $jobId): string
|
||||||
|
{
|
||||||
|
return $this->jobsDir . '/' . $jobId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function escapeArgument(string $arg): string
|
||||||
|
{
|
||||||
|
if (Utils::isWindows()) {
|
||||||
|
$escaped = str_replace('"', '""', $arg);
|
||||||
|
|
||||||
|
return '"' . $escaped . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return escapeshellarg($arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateJobId(): string
|
||||||
|
{
|
||||||
|
return 'job-' . gmdate('YmdHis') . '-' . substr(md5(uniqid('', true)), 0, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeManifest(array $data): void
|
||||||
|
{
|
||||||
|
if (!$this->jobManifestPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$existing = [];
|
||||||
|
if (is_file($this->jobManifestPath)) {
|
||||||
|
$decoded = json_decode((string)file_get_contents($this->jobManifestPath), true);
|
||||||
|
if (is_array($decoded)) {
|
||||||
|
$existing = $decoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $existing + [
|
||||||
|
'id' => $this->jobId,
|
||||||
|
'created_at' => time(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$payload = array_merge($payload, $data, [
|
||||||
|
'updated_at' => time(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Folder::create(dirname($this->jobManifestPath));
|
||||||
|
file_put_contents($this->jobManifestPath, json_encode($payload, JSON_PRETTY_PRINT));
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
// ignore manifest write failures
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateJob(array $data): void
|
||||||
|
{
|
||||||
|
$this->writeManifest($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markJobError(string $message): void
|
||||||
|
{
|
||||||
|
$this->setProgress('error', $message, null, ['message' => $message]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function readManifest(?string $path = null): array
|
||||||
|
{
|
||||||
|
$target = $path ?? $this->jobManifestPath;
|
||||||
|
if (!$target || !is_file($target)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = json_decode((string)file_get_contents($target), true);
|
||||||
|
|
||||||
|
return is_array($decoded) ? $decoded : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadJob(string $jobId): array
|
||||||
|
{
|
||||||
|
$this->setJobId($jobId);
|
||||||
|
|
||||||
|
return $this->readManifest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJobStatus(string $jobId): array
|
||||||
|
{
|
||||||
|
$manifest = $this->loadJob($jobId);
|
||||||
|
$progress = $this->getProgress();
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'job' => $manifest ?: null,
|
||||||
|
'progress' => $progress,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->clearJobContext();
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function queue(array $options = []): array
|
||||||
|
{
|
||||||
|
$jobId = $this->generateJobId();
|
||||||
|
$this->setJobId($jobId);
|
||||||
|
|
||||||
|
$jobDir = $this->getJobDir($jobId);
|
||||||
|
Folder::create($jobDir);
|
||||||
|
|
||||||
|
$logPath = $jobDir . '/worker.log';
|
||||||
|
|
||||||
|
$timestamp = time();
|
||||||
|
|
||||||
|
$manifest = [
|
||||||
|
'id' => $jobId,
|
||||||
|
'status' => 'queued',
|
||||||
|
'options' => $options,
|
||||||
|
'log' => $logPath,
|
||||||
|
'created_at' => $timestamp,
|
||||||
|
'started_at' => null,
|
||||||
|
'completed_at' => null,
|
||||||
|
];
|
||||||
|
$this->writeManifest($manifest);
|
||||||
|
|
||||||
|
try {
|
||||||
|
file_put_contents($logPath, '[' . gmdate('c') . "] Job {$jobId} queued\n");
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
// ignore log write failures
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setProgress('queued', 'Waiting for upgrade worker...', 0, ['job_id' => $jobId]);
|
||||||
|
|
||||||
|
if (!function_exists('proc_open')) {
|
||||||
|
$message = 'proc_open() is disabled on this server; unable to run safe upgrade worker.';
|
||||||
|
$this->writeManifest([
|
||||||
|
'status' => 'error',
|
||||||
|
'error' => $message,
|
||||||
|
]);
|
||||||
|
$this->setProgress('error', $message, null, ['job_id' => $jobId]);
|
||||||
|
$this->clearJobContext();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $message,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$phpBinary = $this->escapeArgument(PHP_BINARY);
|
||||||
|
$gravBinary = Utils::isWindows()
|
||||||
|
? $this->escapeArgument(GRAV_ROOT . '\\bin\\grav')
|
||||||
|
: $this->escapeArgument(GRAV_ROOT . '/bin/grav');
|
||||||
|
$jobArgument = $this->escapeArgument($jobId);
|
||||||
|
$logArgument = $this->escapeArgument($logPath);
|
||||||
|
|
||||||
|
if (Utils::isWindows()) {
|
||||||
|
$commandLine = sprintf(
|
||||||
|
'start /B "" %s %s safe-upgrade:run --job=%s >> %s 2>&1',
|
||||||
|
$phpBinary,
|
||||||
|
$gravBinary,
|
||||||
|
$jobArgument,
|
||||||
|
$logArgument
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$commandLine = sprintf(
|
||||||
|
'%s %s safe-upgrade:run --job=%s >> %s 2>&1 &',
|
||||||
|
$phpBinary,
|
||||||
|
$gravBinary,
|
||||||
|
$jobArgument,
|
||||||
|
$logArgument
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$descriptor = [
|
||||||
|
0 => ['pipe', 'r'],
|
||||||
|
1 => ['pipe', 'w'],
|
||||||
|
2 => ['pipe', 'w'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$process = proc_open($commandLine, $descriptor, $pipes, GRAV_ROOT);
|
||||||
|
if (!is_resource($process)) {
|
||||||
|
throw new RuntimeException('Unable to start safe upgrade worker.');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($pipes as $pipe) {
|
||||||
|
if (is_resource($pipe)) {
|
||||||
|
fclose($pipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_close($process);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$this->writeManifest([
|
||||||
|
'status' => 'error',
|
||||||
|
'error' => $message,
|
||||||
|
]);
|
||||||
|
$this->setProgress('error', $message, null, ['job_id' => $jobId]);
|
||||||
|
$this->clearJobContext();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $message,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeManifest([
|
||||||
|
'status' => 'running',
|
||||||
|
'started_at' => time(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status' => 'queued',
|
||||||
|
'job_id' => $jobId,
|
||||||
|
'log' => $logPath,
|
||||||
|
'progress' => $this->getProgress(),
|
||||||
|
'job' => $this->readManifest(),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -287,6 +537,17 @@ class SafeUpgradeManager
|
|||||||
'manifest' => $manifest,
|
'manifest' => $manifest,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($this->jobManifestPath) {
|
||||||
|
$this->updateJob([
|
||||||
|
'result' => [
|
||||||
|
'status' => 'success',
|
||||||
|
'version' => $remoteVersion,
|
||||||
|
'previous_version' => $localVersion,
|
||||||
|
'manifest' => $manifest,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'version' => $remoteVersion,
|
'version' => $remoteVersion,
|
||||||
@@ -589,12 +850,40 @@ class SafeUpgradeManager
|
|||||||
'timestamp' => time(),
|
'timestamp' => time(),
|
||||||
] + $extra;
|
] + $extra;
|
||||||
|
|
||||||
|
if ($this->jobId) {
|
||||||
|
$payload['job_id'] = $this->jobId;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Folder::create(dirname($this->progressPath));
|
Folder::create(dirname($this->progressPath));
|
||||||
file_put_contents($this->progressPath, json_encode($payload, JSON_PRETTY_PRINT));
|
file_put_contents($this->progressPath, json_encode($payload, JSON_PRETTY_PRINT));
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
// ignore write failures
|
// ignore write failures
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->jobManifestPath) {
|
||||||
|
$status = 'running';
|
||||||
|
if ($stage === 'error') {
|
||||||
|
$status = 'error';
|
||||||
|
} elseif ($stage === 'complete') {
|
||||||
|
$status = 'success';
|
||||||
|
}
|
||||||
|
|
||||||
|
$manifest = [
|
||||||
|
'status' => $status,
|
||||||
|
'progress' => $payload,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($status === 'success') {
|
||||||
|
$manifest['completed_at'] = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status === 'error' && isset($extra['message'])) {
|
||||||
|
$manifest['error'] = $extra['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeManifest($manifest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -606,7 +895,18 @@ class SafeUpgradeManager
|
|||||||
*/
|
*/
|
||||||
protected function errorResult(string $message, array $extra = []): array
|
protected function errorResult(string $message, array $extra = []): array
|
||||||
{
|
{
|
||||||
$this->setProgress('error', $message, null, $extra);
|
$extraWithMessage = ['message' => $message] + $extra;
|
||||||
|
$this->setProgress('error', $message, null, $extraWithMessage);
|
||||||
|
|
||||||
|
if ($this->jobManifestPath) {
|
||||||
|
$this->updateJob([
|
||||||
|
'result' => [
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $message,
|
||||||
|
'details' => $extra,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const r = (key, value, fallback = '') => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const STAGE_TITLES = {
|
const STAGE_TITLES = {
|
||||||
|
queued: () => t('SAFE_UPGRADE_STAGE_QUEUED', 'Waiting for worker'),
|
||||||
initializing: () => t('SAFE_UPGRADE_STAGE_INITIALIZING', 'Preparing upgrade'),
|
initializing: () => t('SAFE_UPGRADE_STAGE_INITIALIZING', 'Preparing upgrade'),
|
||||||
downloading: () => t('SAFE_UPGRADE_STAGE_DOWNLOADING', 'Downloading update'),
|
downloading: () => t('SAFE_UPGRADE_STAGE_DOWNLOADING', 'Downloading update'),
|
||||||
installing: () => t('SAFE_UPGRADE_STAGE_INSTALLING', 'Installing update'),
|
installing: () => t('SAFE_UPGRADE_STAGE_INSTALLING', 'Installing update'),
|
||||||
@@ -51,6 +52,7 @@ export default class SafeUpgrade {
|
|||||||
this.statusRequest = null;
|
this.statusRequest = null;
|
||||||
this.isPolling = false;
|
this.isPolling = false;
|
||||||
this.active = false;
|
this.active = false;
|
||||||
|
this.jobId = null;
|
||||||
|
|
||||||
this.registerEvents();
|
this.registerEvents();
|
||||||
}
|
}
|
||||||
@@ -347,6 +349,8 @@ export default class SafeUpgrade {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.buttons.start.prop('disabled', true);
|
this.buttons.start.prop('disabled', true);
|
||||||
|
this.stopPolling();
|
||||||
|
this.jobId = null;
|
||||||
|
|
||||||
const body = { decisions: this.decisions };
|
const body = { decisions: this.decisions };
|
||||||
|
|
||||||
@@ -380,19 +384,30 @@ export default class SafeUpgrade {
|
|||||||
this.renderResult(data);
|
this.renderResult(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (data.fallback) {
|
||||||
|
this.renderResult(data);
|
||||||
|
this.stopPolling();
|
||||||
|
this.renderProgress({
|
||||||
|
stage: data.status === 'success' ? 'complete' : 'error',
|
||||||
|
message: data.message || t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete'),
|
||||||
|
percent: data.status === 'success' ? 100 : null,
|
||||||
|
target_version: data.version || (data.manifest && data.manifest.target_version) || null,
|
||||||
|
manifest: data.manifest || null
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.renderResult(data);
|
if (data.status === 'queued' && data.job_id) {
|
||||||
this.stopPolling();
|
this.jobId = data.job_id;
|
||||||
this.renderProgress({
|
if (data.progress) {
|
||||||
stage: 'complete',
|
this.renderProgress(data.progress);
|
||||||
message: data.message || t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete'),
|
}
|
||||||
percent: 100,
|
this.beginPolling(1200);
|
||||||
target_version: data.version || (data.manifest && data.manifest.target_version) || null,
|
} else {
|
||||||
manifest: data.manifest || null
|
this.renderResult(data);
|
||||||
});
|
this.stopPolling();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.beginPolling(1200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beginPolling(delay = 1200) {
|
beginPolling(delay = 1200) {
|
||||||
@@ -432,7 +447,9 @@ export default class SafeUpgrade {
|
|||||||
|
|
||||||
console.debug('[SafeUpgrade] poll status');
|
console.debug('[SafeUpgrade] poll status');
|
||||||
|
|
||||||
this.statusRequest = request(this.urls.status, (response) => {
|
const statusUrl = this.jobId ? `${this.urls.status}?job=${encodeURIComponent(this.jobId)}` : this.urls.status;
|
||||||
|
|
||||||
|
this.statusRequest = request(statusUrl, (response) => {
|
||||||
console.debug('[SafeUpgrade] status response', response);
|
console.debug('[SafeUpgrade] status response', response);
|
||||||
|
|
||||||
if (response.status === 'error') {
|
if (response.status === 'error') {
|
||||||
@@ -447,10 +464,15 @@ export default class SafeUpgrade {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = response.data || {};
|
const payload = response.data || {};
|
||||||
|
const data = payload.progress || payload;
|
||||||
nextStage = data.stage || null;
|
nextStage = data.stage || null;
|
||||||
this.renderProgress(data);
|
this.renderProgress(data);
|
||||||
|
|
||||||
|
if (payload.job && payload.job.status === 'success') {
|
||||||
|
shouldContinue = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (nextStage === 'installing' || nextStage === 'finalizing' || nextStage === 'complete') {
|
if (nextStage === 'installing' || nextStage === 'finalizing' || nextStage === 'complete') {
|
||||||
shouldContinue = false;
|
shouldContinue = false;
|
||||||
}
|
}
|
||||||
@@ -465,10 +487,12 @@ export default class SafeUpgrade {
|
|||||||
|
|
||||||
if (nextStage === 'complete' || nextStage === 'error') {
|
if (nextStage === 'complete' || nextStage === 'error') {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
|
this.jobId = null;
|
||||||
} else if (shouldContinue) {
|
} else if (shouldContinue) {
|
||||||
this.schedulePoll();
|
this.schedulePoll();
|
||||||
} else {
|
} else {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
|
this.jobId = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
49
themes/grav/js/admin.min.js
vendored
49
themes/grav/js/admin.min.js
vendored
@@ -4562,6 +4562,9 @@ var r = function r(key, value) {
|
|||||||
return template.replace('%s', value);
|
return template.replace('%s', value);
|
||||||
};
|
};
|
||||||
var STAGE_TITLES = {
|
var STAGE_TITLES = {
|
||||||
|
queued: function queued() {
|
||||||
|
return t('SAFE_UPGRADE_STAGE_QUEUED', 'Waiting for worker');
|
||||||
|
},
|
||||||
initializing: function initializing() {
|
initializing: function initializing() {
|
||||||
return t('SAFE_UPGRADE_STAGE_INITIALIZING', 'Preparing upgrade');
|
return t('SAFE_UPGRADE_STAGE_INITIALIZING', 'Preparing upgrade');
|
||||||
},
|
},
|
||||||
@@ -4605,6 +4608,7 @@ var SafeUpgrade = /*#__PURE__*/function () {
|
|||||||
this.statusRequest = null;
|
this.statusRequest = null;
|
||||||
this.isPolling = false;
|
this.isPolling = false;
|
||||||
this.active = false;
|
this.active = false;
|
||||||
|
this.jobId = null;
|
||||||
this.registerEvents();
|
this.registerEvents();
|
||||||
}
|
}
|
||||||
return safe_upgrade_createClass(SafeUpgrade, [{
|
return safe_upgrade_createClass(SafeUpgrade, [{
|
||||||
@@ -4813,6 +4817,8 @@ var SafeUpgrade = /*#__PURE__*/function () {
|
|||||||
percent: 0
|
percent: 0
|
||||||
});
|
});
|
||||||
this.buttons.start.prop('disabled', true);
|
this.buttons.start.prop('disabled', true);
|
||||||
|
this.stopPolling();
|
||||||
|
this.jobId = null;
|
||||||
var body = {
|
var body = {
|
||||||
decisions: this.decisions
|
decisions: this.decisions
|
||||||
};
|
};
|
||||||
@@ -4847,17 +4853,29 @@ var SafeUpgrade = /*#__PURE__*/function () {
|
|||||||
_this4.renderResult(data);
|
_this4.renderResult(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_this4.renderResult(data);
|
if (data.fallback) {
|
||||||
_this4.stopPolling();
|
_this4.renderResult(data);
|
||||||
_this4.renderProgress({
|
_this4.stopPolling();
|
||||||
stage: 'complete',
|
_this4.renderProgress({
|
||||||
message: data.message || t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete'),
|
stage: data.status === 'success' ? 'complete' : 'error',
|
||||||
percent: 100,
|
message: data.message || t('SAFE_UPGRADE_STAGE_COMPLETE', 'Upgrade complete'),
|
||||||
target_version: data.version || data.manifest && data.manifest.target_version || null,
|
percent: data.status === 'success' ? 100 : null,
|
||||||
manifest: data.manifest || null
|
target_version: data.version || data.manifest && data.manifest.target_version || null,
|
||||||
});
|
manifest: data.manifest || null
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.status === 'queued' && data.job_id) {
|
||||||
|
_this4.jobId = data.job_id;
|
||||||
|
if (data.progress) {
|
||||||
|
_this4.renderProgress(data.progress);
|
||||||
|
}
|
||||||
|
_this4.beginPolling(1200);
|
||||||
|
} else {
|
||||||
|
_this4.renderResult(data);
|
||||||
|
_this4.stopPolling();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.beginPolling(1200);
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "beginPolling",
|
key: "beginPolling",
|
||||||
@@ -4902,7 +4920,8 @@ var SafeUpgrade = /*#__PURE__*/function () {
|
|||||||
var nextStage = null;
|
var nextStage = null;
|
||||||
var shouldContinue = true;
|
var shouldContinue = true;
|
||||||
console.debug('[SafeUpgrade] poll status');
|
console.debug('[SafeUpgrade] poll status');
|
||||||
this.statusRequest = utils_request(this.urls.status, function (response) {
|
var statusUrl = this.jobId ? "".concat(this.urls.status, "?job=").concat(encodeURIComponent(this.jobId)) : this.urls.status;
|
||||||
|
this.statusRequest = utils_request(statusUrl, function (response) {
|
||||||
console.debug('[SafeUpgrade] status response', response);
|
console.debug('[SafeUpgrade] status response', response);
|
||||||
if (response.status === 'error') {
|
if (response.status === 'error') {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
@@ -4915,9 +4934,13 @@ var SafeUpgrade = /*#__PURE__*/function () {
|
|||||||
nextStage = 'error';
|
nextStage = 'error';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var data = response.data || {};
|
var payload = response.data || {};
|
||||||
|
var data = payload.progress || payload;
|
||||||
nextStage = data.stage || null;
|
nextStage = data.stage || null;
|
||||||
_this6.renderProgress(data);
|
_this6.renderProgress(data);
|
||||||
|
if (payload.job && payload.job.status === 'success') {
|
||||||
|
shouldContinue = false;
|
||||||
|
}
|
||||||
if (nextStage === 'installing' || nextStage === 'finalizing' || nextStage === 'complete') {
|
if (nextStage === 'installing' || nextStage === 'finalizing' || nextStage === 'complete') {
|
||||||
shouldContinue = false;
|
shouldContinue = false;
|
||||||
}
|
}
|
||||||
@@ -4929,10 +4952,12 @@ var SafeUpgrade = /*#__PURE__*/function () {
|
|||||||
}
|
}
|
||||||
if (nextStage === 'complete' || nextStage === 'error') {
|
if (nextStage === 'complete' || nextStage === 'error') {
|
||||||
_this6.stopPolling();
|
_this6.stopPolling();
|
||||||
|
_this6.jobId = null;
|
||||||
} else if (shouldContinue) {
|
} else if (shouldContinue) {
|
||||||
_this6.schedulePoll();
|
_this6.schedulePoll();
|
||||||
} else {
|
} else {
|
||||||
_this6.stopPolling();
|
_this6.stopPolling();
|
||||||
|
_this6.jobId = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.statusRequest.then(finalize, finalize);
|
this.statusRequest.then(finalize, finalize);
|
||||||
|
|||||||
Reference in New Issue
Block a user