Skip to content

Commit

Permalink
split sql queries execution
Browse files Browse the repository at this point in the history
  • Loading branch information
Morgan Pichat committed Oct 17, 2024
1 parent c52adec commit deccebd
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 239 deletions.
9 changes: 9 additions & 0 deletions classes/Parameters/UpgradeFileNames.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ class UpgradeFileNames
*/
const FILES_TO_UPGRADE_LIST = 'filesToUpgrade.list';

/**
* during upgradeFiles process,
* this files contains the list of files left to upgrade in a serialized array.
* (this file is deleted in init() method if you reload the page).
*
* @var string
*/
const SQL_TO_EXECUTE_LIST = 'sqlToExecute.list';

/**
* during upgradeModules process,
* this files contains the list of modules left to upgrade in a serialized array.
Expand Down
64 changes: 62 additions & 2 deletions classes/Progress/Backlog.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,69 @@ public function getNext()
return array_pop($this->backlog);
}

public function getRemainingTotal(): int
/**
* @return int|string|null
*/
public function getFirstKey()
{
return count($this->backlog);
if (empty($this->backlog)) {
return null;
}

reset($this->backlog);

return key($this->backlog);
}

/**
* @return mixed|null
*/
public function getFirstValue()
{
if (empty($this->backlog)) {
return null;
}

return reset($this->backlog);
}

/**
* @param int|string $key
* @param mixed $content
*/
public function updateItem($key, $content): void
{
if (empty($content)) {
unset($this->backlog[$key]);
} else {
$this->backlog[$key] = $content;
}
}

public function getRemainingTotal(int $depth = 1): int
{
return $this->countElements($this->backlog, $depth);
}

/**
* @param mixed[] $array
*/
private function countElements(array $array, int $depth): int
{
if ($depth === 1) {
return count($array);
}

$total = 0;
foreach ($array as $value) {
if (is_array($value)) {
$total += $this->countElements($value, $depth - 1);
} else {
++$total;
}
}

return $total;
}

public function getInitialTotal(): int
Expand Down
4 changes: 2 additions & 2 deletions classes/Progress/CompletionCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public function getBasePercentageOfTask(string $taskName): int
/**
* @return int<0, 100>
*/
public function computePercentage(Backlog $backlog, string $currentTaskClass, string $nextTaskClass): int
public function computePercentage(Backlog $backlog, string $currentTaskClass, string $nextTaskClass, int $backlogDepth = 1): int
{
$currentBaseProgress = $this->getBasePercentageOfTask($currentTaskClass);
$nextBaseProgress = $this->getBasePercentageOfTask($nextTaskClass);
Expand All @@ -108,6 +108,6 @@ public function computePercentage(Backlog $backlog, string $currentTaskClass, st
}

// Casting as integer is equivalent to using floor(), and we want to round down.
return (int) ($currentBaseProgress + (($nextBaseProgress - $currentBaseProgress) * ($backlog->getInitialTotal() - $backlog->getRemainingTotal()) / $backlog->getInitialTotal()));
return (int) ($currentBaseProgress + (($nextBaseProgress - $currentBaseProgress) * ($backlog->getInitialTotal() - $backlog->getRemainingTotal($backlogDepth)) / $backlog->getInitialTotal()));
}
}
131 changes: 117 additions & 14 deletions classes/Task/Update/UpdateDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@

namespace PrestaShop\Module\AutoUpgrade\Task\Update;

use Exception;
use PrestaShop\Module\AutoUpgrade\Exceptions\UpgradeException;
use PrestaShop\Module\AutoUpgrade\Parameters\UpgradeFileNames;
use PrestaShop\Module\AutoUpgrade\Progress\Backlog;
use PrestaShop\Module\AutoUpgrade\Task\AbstractTask;
use PrestaShop\Module\AutoUpgrade\Task\ExitCode;
use PrestaShop\Module\AutoUpgrade\Task\TaskName;
Expand All @@ -36,19 +39,50 @@
use PrestaShop\Module\AutoUpgrade\UpgradeTools\CoreUpgrader\CoreUpgrader17;
use PrestaShop\Module\AutoUpgrade\UpgradeTools\CoreUpgrader\CoreUpgrader80;
use PrestaShop\Module\AutoUpgrade\UpgradeTools\CoreUpgrader\CoreUpgrader81;
use PrestaShop\Module\AutoUpgrade\VersionUtils;

class UpdateDatabase extends AbstractTask
{
const TASK_TYPE = TaskType::TASK_TYPE_UPDATE;

/** @var CoreUpgrader */
private $coreUpgrader;

public function run(): int
{
$this->container->getState()->setProgressPercentage(
$this->container->getCompletionCalculator()->getBasePercentageOfTask(self::class)
);

try {
$this->getCoreUpgrader()->doUpgrade();
if (!$this->container->getFileConfigurationStorage()->exists(UpgradeFileNames::SQL_TO_EXECUTE_LIST)) {
$this->warmUp();
$originVersion = $this->container->getState()->getOriginVersion();
$sqlContentList = $this->getCoreUpgrader()->getSqlContentList($originVersion);

$totalQueries = 0;
foreach ($sqlContentList as $queries) {
$totalQueries += count($queries);
}

$backlog = new Backlog($sqlContentList, $totalQueries);
} else {
$this->getCoreUpgrader()->setupUpdateEnvironment();
$backlog = Backlog::fromContents($this->container->getFileConfigurationStorage()->load(UpgradeFileNames::SQL_TO_EXECUTE_LIST));
}

if ($backlog->getRemainingTotal(2) > 0) {
$this->logger->info($this->translator->trans('Update database in progress. %d queries left', [$backlog->getRemainingTotal(2)]));

$this->updateDatabase($backlog);

$this->container->getState()->setProgressPercentage(
$this->container->getCompletionCalculator()->computePercentage($backlog, self::class, UpdateModules::class, 2)
);

$this->next = TaskName::TASK_UPDATE_DATABASE;
$this->stepDone = false;

return ExitCode::SUCCESS;
}
$this->container->getFileConfigurationStorage()->clean(UpgradeFileNames::SQL_TO_EXECUTE_LIST);
$this->getCoreUpgrader()->finalizeCoreUpdate();
} catch (UpgradeException $e) {
$this->next = TaskName::TASK_ERROR;
$this->setErrorFlag();
Expand All @@ -69,26 +103,95 @@ public function run(): int

public function getCoreUpgrader(): CoreUpgrader
{
if (version_compare($this->container->getState()->getInstallVersion(), '8', '<')) {
return new CoreUpgrader17($this->container, $this->logger);
if ($this->coreUpgrader !== null) {
return $this->coreUpgrader;
}

if (version_compare($this->container->getState()->getInstallVersion(), '8.1', '<')) {
return new CoreUpgrader80($this->container, $this->logger);
if (version_compare($this->container->getState()->getInstallVersion(), '8', '<')) {
$this->coreUpgrader = new CoreUpgrader17($this->container, $this->logger);
} elseif (version_compare($this->container->getState()->getInstallVersion(), '8.1', '<')) {
$this->coreUpgrader = new CoreUpgrader80($this->container, $this->logger);
} else {
$this->coreUpgrader = new CoreUpgrader81($this->container, $this->logger);
}

return new CoreUpgrader81($this->container, $this->logger);
return $this->coreUpgrader;
}

public function init(): void
{
$this->logger->info($this->translator->trans('Cleaning file cache'));
$this->container->getCacheCleaner()->cleanFolders();
$this->logger->info($this->translator->trans('Running opcache_reset'));
$this->container->resetOpcache();
if (!$this->container->getFileConfigurationStorage()->exists(UpgradeFileNames::SQL_TO_EXECUTE_LIST)) {
$this->logger->info($this->translator->trans('Cleaning file cache'));
$this->container->getCacheCleaner()->cleanFolders();
$this->logger->info($this->translator->trans('Running opcache_reset'));
$this->container->resetOpcache();
}

// Migrating settings file
$this->container->initPrestaShopAutoloader();
parent::init();
}

/**
* First call of this task needs a warmup, where we load the files list to be upgraded.
*
* @throws UpgradeException
* @throws Exception
*/
protected function warmUp(): int
{
$this->logger->info($this->container->getTranslator()->trans('Updating database data and structure'));

$this->container->getState()->setProgressPercentage(
$this->container->getCompletionCalculator()->getBasePercentageOfTask(self::class)
);

$this->getCoreUpgrader()->writeNewSettings();

$this->logger->info($this->container->getTranslator()->trans('Checking version validity'));
$this->checkVersionIsNewer();

$this->getCoreUpgrader()->setupUpdateEnvironment();

if ($this->container->getUpgradeConfiguration()->shouldDeactivateCustomModules()) {
$this->logger->info($this->container->getTranslator()->trans('Disabling all non native modules'));
$this->getCoreUpgrader()->disableCustomModules();
} else {
$this->logger->info($this->container->getTranslator()->trans('Keeping non native modules enabled'));
}

return ExitCode::SUCCESS;
}

/**
* @throws UpgradeException
*/
protected function checkVersionIsNewer(): void
{
$originVersion = VersionUtils::normalizePrestaShopVersion($this->container->getState()->getOriginVersion());
$installVersion = VersionUtils::normalizePrestaShopVersion($this->container->getState()->getInstallVersion());

$versionCompare = version_compare($installVersion, $originVersion);

if ($versionCompare === -1) {
throw new UpgradeException($this->container->getTranslator()->trans('[ERROR] Version to install is too old.') . ' ' . $this->container->getTranslator()->trans('Current version: %oldversion%. Version to install: %newversion%.', ['%oldversion%' => $originVersion, '%newversion%' => $installVersion]));
} elseif ($versionCompare === 0) {
throw new UpgradeException($this->container->getTranslator()->trans('You already have the %s version.', [$installVersion]));
}
}

protected function updateDatabase(Backlog $backlog): void
{
$upgradeFile = $backlog->getFirstKey();
$sqlContent = $backlog->getFirstValue();

$query = reset($sqlContent);
$queryIndex = key($sqlContent);

$this->getCoreUpgrader()->runQuery($upgradeFile, $query);

unset($sqlContent[$queryIndex]);
$backlog->updateItem($upgradeFile, $sqlContent);
$this->container->getFileConfigurationStorage()->save($backlog->dump(), UpgradeFileNames::SQL_TO_EXECUTE_LIST);
}
}
Loading

0 comments on commit deccebd

Please sign in to comment.