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
* Repair unit tests
* Move check for duplicate sites to getAvailableSites. PhpStan
* Remove unused imports

Fixes: #3939
Ports: #4154
Replaces: #4145
  • Loading branch information
sfroemkenjw authored and dkd-kaehm committed Dec 17, 2024
1 parent 27f36af commit d80e037
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,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 @@ -148,9 +147,7 @@ protected function autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable(): b
*/
protected function initializeView(ViewInterface|FluidStandaloneViewInterface $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('selectedPageUID', $this->selectedPageUID);
if ($this->selectedPageUID < 1) {
Expand Down
78 changes: 63 additions & 15 deletions Classes/Domain/Site/SiteRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use ApacheSolrForTypo3\Solr\System\Records\Pages\PagesRepository;
use ApacheSolrForTypo3\Solr\System\Util\SiteUtility;
use Doctrine\DBAL\Exception as DBALException;
use Generator;
use Throwable;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
Expand Down Expand Up @@ -103,8 +104,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 +124,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 +210,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 Classes/ViewHelpers/SearchFormViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
/**
* Class SearchFormViewHelper
*
*
* @property RenderingContext $renderingContext
*/
class SearchFormViewHelper extends AbstractSolrFrontendTagBasedViewHelper
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 d80e037

Please sign in to comment.