[BUGFIX] Avoid clearing the page cache too often
authorAlexander Schnitzler <alex.schnitzler@typovision.de>
Fri, 4 Jan 2013 18:38:21 +0000 (19:38 +0100)
committerMarkus Günther <mail@markus-guenther.de>
Mon, 7 Jan 2013 08:34:19 +0000 (09:34 +0100)
Instead of clearing the page cache on every
create, update and delete action, implement
a page id stack which will be cleared at the
end of the request.

Releases: 6.1, 6.0
Fixes: #6117
Change-Id: I3703011e6cd2db9c6a4f32ba27ef09ecb25954f3
Reviewed-on: https://review.typo3.org/17373
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Stefan Neufeind
Reviewed-by: Markus Günther
Tested-by: Markus Günther
typo3/sysext/extbase/Classes/Core/Bootstrap.php
typo3/sysext/extbase/Classes/Mvc/Controller/AbstractController.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
typo3/sysext/extbase/Classes/Service/CacheService.php
typo3/sysext/extbase/Tests/Unit/Service/CacheServiceTest.php

index a04f89e..4b57ba1 100644 (file)
@@ -200,6 +200,8 @@ class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface {
                } else {
                        $content = $this->handleWebRequest();
                }
+
+               $this->objectManager->get('TYPO3\CMS\Extbase\Service\CacheService')->clearCachesOfRegisteredPageIds();
                return $content;
        }
 
index eda35f8..6a557f4 100644 (file)
@@ -352,6 +352,9 @@ abstract class AbstractController implements \TYPO3\CMS\Extbase\Mvc\Controller\C
                if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
                        throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539734);
                }
+
+               $this->objectManager->get('TYPO3\CMS\Extbase\Service\CacheService')->clearCachesOfRegisteredPageIds();
+
                $uri = $this->addBaseUriIfNecessary($uri);
                $escapedUri = htmlentities($uri, ENT_QUOTES, 'utf-8');
                $this->response->setContent('<html><head><meta http-equiv="refresh" content="' . intval($delay) . ';url=' . $escapedUri . '"/></head></html>');
@@ -442,4 +445,4 @@ abstract class AbstractController implements \TYPO3\CMS\Extbase\Mvc\Controller\C
        }
 }
 
-?>
\ No newline at end of file
+?>
index b18c339..34d1f6d 100644 (file)
@@ -1232,8 +1232,10 @@ class Typo3DbBackend implements \TYPO3\CMS\Extbase\Persistence\Generic\Storage\B
                                }
                        }
                }
-               // TODO check if we can hand this over to the Dispatcher to clear the page only once, this will save around 10% time while inserting and updating
-               $this->cacheService->clearPageCache($pageIdsToClear);
+
+               foreach ($pageIdsToClear as $pageIdToClear) {
+                       $this->cacheService->getPageIdStack()->push($pageIdToClear);
+               }
        }
 
        /**
index fdda07a..c73f02e 100644 (file)
@@ -33,12 +33,32 @@ namespace TYPO3\CMS\Extbase\Service;
 class CacheService implements \TYPO3\CMS\Core\SingletonInterface {
 
        /**
+        * @var \SplStack
+        */
+       protected $pageIdStack;
+
+       /**
+        * Initializes the pageIdStack
+        */
+       public function __construct() {
+               $this->pageIdStack = new \SplStack;
+       }
+
+       /**
+        * @return \SplStack
+        */
+       public function getPageIdStack() {
+               return $this->pageIdStack;
+       }
+
+       /**
         * Clears the page cache
         *
         * @param mixed $pageIdsToClear (integer) single or (array) multiple pageIds to clear the cache for
         * @return void
         */
        public function clearPageCache($pageIdsToClear = NULL) {
+
                if ($pageIdsToClear !== NULL && !is_array($pageIdsToClear)) {
                        $pageIdsToClear = array(intval($pageIdsToClear));
                }
@@ -79,6 +99,23 @@ class CacheService implements \TYPO3\CMS\Core\SingletonInterface {
                        $pageSectionCache->flush();
                }
        }
+
+       /**
+        * Walks through the pageIdStack, collects all pageIds
+        * as array and passes them on to clearPageCache.
+        *
+        * @return void
+        */
+       public function clearCachesOfRegisteredPageIds() {
+               if (!$this->pageIdStack->isEmpty()) {
+                       $pageIds = array();
+                       while (!$this->pageIdStack->isEmpty()) {
+                               $pageIds[] = intval($this->pageIdStack->pop());
+                       }
+                       $pageIds = array_values(array_unique($pageIds));
+                       $this->clearPageCache($pageIds);
+               }
+       }
 }
 
 ?>
\ No newline at end of file
index da70e43..92bc4fe 100644 (file)
@@ -129,6 +129,39 @@ class CacheServiceTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $GLOBALS['typo3CacheManager']->expects($this->once())->method('getCache')->with('cache_pagesection')->will($this->returnValue($mockCacheFrontend));
                $this->cacheService->_call('flushPageSectionCache');
        }
+
+       /**
+        * @test
+        * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
+        */
+       public function clearsCachesOfRegisteredPageIds() {
+
+               $cacheService = $this->getMock('TYPO3\\CMS\\Extbase\\Service\\CacheService', array('flushPageCache', 'flushPageSectionCache'));
+               $cacheService->getPageIdStack()->push(8);
+               $cacheService->getPageIdStack()->push(15);
+               $cacheService->getPageIdStack()->push(2);
+
+               $cacheService->expects($this->once())->method('flushPageCache')->with(array(2,15,8));
+               $cacheService->expects($this->once())->method('flushPageSectionCache')->with(array(2,15,8));
+               $cacheService->clearCachesOfRegisteredPageIds();
+       }
+
+       /**
+        * @test
+        * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
+        */
+       public function clearsCachesOfDuplicateRegisteredPageIdsOnlyOnce() {
+
+               $cacheService = $this->getMock('TYPO3\\CMS\\Extbase\\Service\\CacheService', array('flushPageCache', 'flushPageSectionCache'));
+               $cacheService->getPageIdStack()->push(8);
+               $cacheService->getPageIdStack()->push(15);
+               $cacheService->getPageIdStack()->push(15);
+               $cacheService->getPageIdStack()->push(2);
+
+               $cacheService->expects($this->once())->method('flushPageCache')->with(array(2, 15, 8));
+               $cacheService->expects($this->once())->method('flushPageSectionCache')->with(array(2, 15, 8));
+               $cacheService->clearCachesOfRegisteredPageIds();
+       }
 }
 
 ?>
\ No newline at end of file