Skip to content

Commit

Permalink
[FEATURE] Use PHP generator to prevent processing of all available site
Browse files Browse the repository at this point in the history
Use PHP generator with yield to process just the available sites needed
How to test

With over 300 root pages it needs over 30 seconds to build up all available sites. With help of a PHP generator we can stop processing all available sites if just the first site is requested. It's also helpful to just check, if there are available sites.

This should speed up performance a lot.

* Remove cache storing from <has> methods of SiteRepository
* Use hasAvailableSites in ModuleController
* Remove cache-set check from tests for SiteRepository
* Move check for duplicate sites to getAvailableSites. PhpStan

Fixes: #3939
Replaces: #4154
  • Loading branch information
sfroemkenjw authored and dkd-kaehm committed Dec 17, 2024
1 parent 7369adf commit fe71a4f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,8 @@ protected function initializeAction(): void
*/
protected function autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable(): bool
{
$solrConfiguredSites = $this->siteRepository->getAvailableSites();
$availableSites = $this->siteFinder->getAllSites();
if (count($solrConfiguredSites) === 1 && count($availableSites) === 1) {
if (count($availableSites) === 1 && $this->siteRepository->hasExactlyOneAvailableSite()) {
$this->selectedSite = $this->siteRepository->getFirstAvailableSite();

// we only overwrite the selected pageUid when no id was passed
Expand All @@ -147,9 +146,7 @@ protected function autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable(): b
*/
protected function initializeView($view): void
{
$sites = $this->siteRepository->getAvailableSites();

$selectOtherPage = count($sites) > 0 || $this->selectedPageUID < 1;
$selectOtherPage = $this->siteRepository->hasAvailableSites() || $this->selectedPageUID < 1;
$this->moduleTemplate->assign('showSelectOtherPage', $selectOtherPage);
$this->moduleTemplate->assign('pageUID', $this->selectedPageUID);
if ($this->selectedPageUID < 1) {
Expand Down
77 changes: 62 additions & 15 deletions Classes/Domain/Site/SiteRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,12 @@ public function getSiteByRootPageId(int $rootPageId): ?Site
*/
public function getFirstAvailableSite(bool $stopOnInvalidSite = false): ?Site
{
$sites = $this->getAvailableSites($stopOnInvalidSite);
return array_shift($sites);
$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

$site = $siteGenerator->current();

return $site instanceof Site ? $site : null;
}

/**
Expand All @@ -119,37 +123,81 @@ public function getAvailableSites(bool $stopOnInvalidSite = false): array
$cacheId = 'SiteRepository' . '_' . 'getAvailableSites';

$sites = $this->runtimeCache->get($cacheId);
if (!empty($sites)) {
if (is_array($sites) && $sites !== []) {
return $sites;
}

$sites = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

$sites = [];
foreach ($siteGenerator as $rootPageId => $site) {
if (isset($sites[$rootPageId])) {
//get each site only once
continue;
}
$sites[$rootPageId] = $site;
}
$this->runtimeCache->set($cacheId, $sites);

return $sites;
}

/**
* Check, if there are any managed sites available
*
* @throws UnexpectedTYPO3SiteInitializationException
*/
public function hasAvailableSites(bool $stopOnInvalidSite = false): bool
{
$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

return ($site = $siteGenerator->current()) && $site instanceof Site;
}

/**
* Check, if there is exactly one managed site available
* Needed in AbstractModuleController::autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable
*
* @throws UnexpectedTYPO3SiteInitializationException
*/
public function hasExactlyOneAvailableSite(bool $stopOnInvalidSite = false): bool
{
if (!$this->hasAvailableSites($stopOnInvalidSite)) {
return false;
}

$siteGenerator = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
$siteGenerator->rewind();

// We start with 1 here as we know from hasAvailableSites() above we have at least one site
$counter = 1;
foreach ($siteGenerator as $_) {
if ($counter > 1) {
return false;
}
$counter++;
}

return true;
}

/**
* Returns available TYPO3 sites
*
* @return Site[]
* @return Site[]|\Generator
*
* @throws UnexpectedTYPO3SiteInitializationException
*/
protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): array
protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): \Generator
{
$typo3ManagedSolrSites = [];
$typo3Sites = $this->siteFinder->getAllSites();
foreach ($typo3Sites as $typo3Site) {
foreach ($this->siteFinder->getAllSites() as $typo3Site) {
try {
$rootPageId = $typo3Site->getRootPageId();
if (isset($typo3ManagedSolrSites[$rootPageId])) {
//get each site only once
continue;
}
$typo3ManagedSolrSite = $this->buildSite($rootPageId);
if ($typo3ManagedSolrSite->isEnabled()) {
$typo3ManagedSolrSites[$rootPageId] = $typo3ManagedSolrSite;
yield $rootPageId => $typo3ManagedSolrSite;
}
} catch (Throwable $e) {
if ($stopOnInvalidSite) {
Expand All @@ -161,7 +209,6 @@ protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): array
}
}
}
return $typo3ManagedSolrSites;
}

/**
Expand Down
6 changes: 2 additions & 4 deletions Classes/Report/SiteHandlingStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ public function __construct(
public function getStatus(): array
{
$reports = [];
$sites = $this->siteRepository->getAvailableSites();
if (empty($sites)) {
if (!$this->siteRepository->hasAvailableSites()) {
$reports[] = GeneralUtility::makeInstance(
Status::class,
self::TITLE_SITE_HANDLING_CONFIGURATION,
Expand All @@ -79,8 +78,7 @@ public function getStatus(): array
return $reports;
}

/** @var Site $site */
foreach ($sites as $site) {
foreach ($this->siteRepository->getAvailableSites() as $site) {
if (!($site instanceof Site)) {
$reports[] = GeneralUtility::makeInstance(
Status::class,
Expand Down
1 change: 0 additions & 1 deletion Tests/Unit/Domain/Site/SiteRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ public function canGetFirstAvailableSite(): void
$this->assertThatSitesAreCreatedWithPageIds([333], [
0 => ['language' => 0],
]);
$this->assertCacheIsWritten();

$site = $this->siteRepository->getFirstAvailableSite();
self::assertInstanceOf(Site::class, $site);
Expand Down

0 comments on commit fe71a4f

Please sign in to comment.