| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\CronArchive; |
|
|
| use Exception; |
| use Piwik\CliMulti\Process; |
| use Piwik\Log; |
| use Piwik\Option; |
|
|
| |
| |
| |
| |
| class SharedSiteIds |
| { |
| public const OPTION_DEFAULT = 'SharedSiteIdsToArchive'; |
| public const OPTION_ALL_WEBSITES = 'SharedSiteIdsToArchive_AllWebsites'; |
| public const KEY_TIMESTAMP = '_ResetQueueTime'; |
|
|
| |
| |
| |
| private $optionName; |
|
|
| private $siteIds = array(); |
| private $currentSiteId; |
| private $done = false; |
| private $initialResetQueueTime = null; |
| private $isContinuingPreviousRun = false; |
|
|
| public function __construct($websiteIds, $optionName = self::OPTION_DEFAULT) |
| { |
| $this->optionName = $optionName; |
|
|
| if (empty($websiteIds)) { |
| $websiteIds = array(); |
| } |
|
|
| $self = $this; |
| $this->siteIds = $this->runExclusive(function () use ($self, $websiteIds) { |
| // if there are already sites to be archived registered, prefer the list of existing archive, meaning help |
| // to finish this queue of sites instead of starting a new queue |
| $existingWebsiteIds = $self->getAllSiteIdsToArchive(); |
|
|
| if (!empty($existingWebsiteIds)) { |
| $this->isContinuingPreviousRun = true; |
| return $existingWebsiteIds; |
| } |
|
|
| $self->setQueueWasReset(); |
| $self->setSiteIdsToArchive($websiteIds); |
|
|
| return $websiteIds; |
| }); |
|
|
| $this->initialResetQueueTime = $this->getResetQueueTime(); |
| } |
|
|
| public function setQueueWasReset() |
| { |
| Option::set($this->optionName . self::KEY_TIMESTAMP, floor(microtime(true) * 1000)); |
| } |
|
|
| private function getResetQueueTime() |
| { |
| Option::clearCachedOption($this->optionName . self::KEY_TIMESTAMP); |
| return (int) Option::get($this->optionName . self::KEY_TIMESTAMP); |
| } |
|
|
| public function getInitialSiteIds() |
| { |
| return $this->siteIds; |
| } |
|
|
| |
| |
| |
| |
| |
| public function getNumSites() |
| { |
| return count($this->siteIds); |
| } |
|
|
| |
| |
| |
| |
| |
| public function getNumProcessedWebsites() |
| { |
| if ($this->done) { |
| return $this->getNumSites(); |
| } |
|
|
| if (empty($this->currentSiteId)) { |
| return 0; |
| } |
|
|
| $index = array_search($this->currentSiteId, $this->siteIds); |
|
|
| if (false === $index) { |
| return 0; |
| } |
|
|
| return $index + 1; |
| } |
|
|
| public function setSiteIdsToArchive($siteIds) |
| { |
| if (!empty($siteIds)) { |
| Option::set($this->optionName, implode(',', $siteIds)); |
| } else { |
| Option::delete($this->optionName); |
| } |
| } |
|
|
| public function getAllSiteIdsToArchive() |
| { |
| Option::clearCachedOption($this->optionName); |
| $siteIdsToArchive = Option::get($this->optionName); |
|
|
| if (empty($siteIdsToArchive)) { |
| return array(); |
| } |
|
|
| return explode(',', trim($siteIdsToArchive)); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private function runExclusive($closure) |
| { |
| $process = new Process('archive.sharedsiteids'); |
|
|
| while ($process->isRunning() && $process->getSecondsSinceCreation() < 5) { |
| |
| usleep(25 * 1000); |
| } |
|
|
| $process->startProcess(); |
|
|
| try { |
| $result = $closure(); |
| } catch (Exception $e) { |
| $process->finishProcess(); |
| throw $e; |
| } |
|
|
| $process->finishProcess(); |
|
|
| return $result; |
| } |
|
|
| |
| |
| |
| |
| |
| public function getNextSiteId() |
| { |
| if ($this->done) { |
| |
| |
| return null; |
| } |
|
|
| if ($this->initialResetQueueTime !== $this->getResetQueueTime()) { |
| |
| $this->currentSiteId = null; |
| $this->done = true; |
| Log::debug('The shared site ID queue was reset, stopping.'); |
| return null; |
| } |
|
|
| $self = $this; |
|
|
| $this->currentSiteId = $this->runExclusive(function () use ($self) { |
|
|
| $siteIds = $self->getAllSiteIdsToArchive(); |
|
|
| if (empty($siteIds)) { |
| |
| return null; |
| } |
|
|
| $nextSiteId = array_shift($siteIds); |
|
|
| $self->setSiteIdsToArchive($siteIds); |
|
|
| return $nextSiteId; |
| }); |
|
|
| if (is_null($this->currentSiteId)) { |
| $this->done = true; |
| } |
|
|
| return $this->currentSiteId; |
| } |
|
|
| public static function isSupported() |
| { |
| return Process::isSupported(); |
| } |
|
|
| public function isContinuingPreviousRun(): bool |
| { |
| return $this->isContinuingPreviousRun; |
| } |
| } |
|
|