Update from SS_Cache to Symfony/Cache

This commit is contained in:
Dylan Wagstaff 2017-12-11 12:50:45 +13:00
parent 9a7651b017
commit 17699f2b8a
7 changed files with 49 additions and 60 deletions

View File

@ -28,12 +28,13 @@ class CachedContentFilter extends ContentFilter {
$cacheEnabled = Config::inst()->get(get_class(), 'cache_enabled'); $cacheEnabled = Config::inst()->get(get_class(), 'cache_enabled');
$result = (isset($_GET['flush']) || !$cacheEnabled) $result = (isset($_GET['flush']) || !$cacheEnabled)
? null ? null
: $cache->load($key); : $cache->get($key);
if($result) return $result; if($result) return $result;
// Fallback to generate result // Fallback to generate result
$result = parent::getContent($key, $callback); $result = parent::getContent($key, $callback);
$cache->save($result, $key); $lifetime = Config::inst()->get(ContentFilter::class, 'cache_lifetime') ?: null;
$cache->set($result, $key, $lifetime);
return $result; return $result;
} }
} }

View File

@ -6,7 +6,8 @@ use SS_Cache;
use SilverStripe\VersionFeed\VersionFeedController; use SilverStripe\VersionFeed\VersionFeedController;
use SilverStripe\Core\Config\Config; use SilverStripe\Core\Config\Config;
use Psr\SimpleCache\CacheInterface;
use SilverStripe\Core\Injector\Injector;
@ -41,13 +42,9 @@ abstract class ContentFilter {
* @return Zend_Cache_Frontend * @return Zend_Cache_Frontend
*/ */
protected function getCache() { protected function getCache() {
$cache = \SS_Cache::factory(VersionFeedController::class); return Injector::inst()->get(
$cache->setOption('automatic_serialization', true); CacheInterface::class . '.' . VersionFeedController::class
);
// Map 0 to null for unlimited lifetime
$lifetime = Config::inst()->get(get_class($this), 'cache_lifetime') ?: null;
$cache->setLifetime($lifetime);
return $cache;
} }
/** /**

View File

@ -94,7 +94,7 @@ class RateLimitFilter extends ContentFilter {
// Generate result with rate limiting enabled // Generate result with rate limiting enabled
$limitKey = $this->getCacheKey($key); $limitKey = $this->getCacheKey($key);
$cache = $this->getCache(); $cache = $this->getCache();
if($lockedUntil = $cache->load($limitKey)) { if($lockedUntil = $cache->get($limitKey)) {
if(time() < $lockedUntil) { if(time() < $lockedUntil) {
// Politely inform visitor of limit // Politely inform visitor of limit
$response = new HTTPResponse_Exception('Too Many Requests.', 429); $response = new HTTPResponse_Exception('Too Many Requests.', 429);
@ -102,9 +102,11 @@ class RateLimitFilter extends ContentFilter {
throw $response; throw $response;
} }
} }
$lifetime = Config::inst()->get(ContentFilter::class, 'cache_lifetime') ?: null;
// Apply rate limit // Apply rate limit
$cache->save(time() + $timeout, $limitKey); $cache->set(time() + $timeout, $limitKey, $lifetime);
// Generate results // Generate results
$result = parent::getContent($key, $callback); $result = parent::getContent($key, $callback);
@ -112,7 +114,7 @@ class RateLimitFilter extends ContentFilter {
// Reset rate limit with optional cooldown // Reset rate limit with optional cooldown
if($cooldown = Config::inst()->get(get_class(), 'lock_cooldown')) { if($cooldown = Config::inst()->get(get_class(), 'lock_cooldown')) {
// Set cooldown on successful query execution // Set cooldown on successful query execution
$cache->save(time() + $cooldown, $limitKey); $cache->set(time() + $cooldown, $limitKey, $lifetime);
} else { } else {
// Without cooldown simply disable lock // Without cooldown simply disable lock
$cache->remove($limitKey); $cache->remove($limitKey);

View File

@ -121,7 +121,7 @@ class VersionFeed extends SiteTreeExtension {
$changed = true; $changed = true;
} }
// Copy the link so it can be cached by SS_Cache. // Copy the link so it can be cached.
$version->GeneratedLink = $version->AbsoluteLink(); $version->GeneratedLink = $version->AbsoluteLink();
} }
@ -142,7 +142,7 @@ class VersionFeed extends SiteTreeExtension {
$first = clone($previous); $first = clone($previous);
$first->DiffContent = new HTMLText(); $first->DiffContent = new HTMLText();
$first->DiffContent->setValue('<div>' . $first->Content . '</div>'); $first->DiffContent->setValue('<div>' . $first->Content . '</div>');
// Copy the link so it can be cached by SS_Cache. // Copy the link so it can be cached.
$first->GeneratedLink = $first->AbsoluteLink(); $first->GeneratedLink = $first->AbsoluteLink();
$changeList->push($first); $changeList->push($first);
} }

View File

@ -2,17 +2,6 @@
namespace SilverStripe\VersionFeed; namespace SilverStripe\VersionFeed;
use SilverStripe\Core\Config\Config; use SilverStripe\Core\Config\Config;
use SilverStripe\VersionFeed\VersionFeed; use SilverStripe\VersionFeed\VersionFeed;
use SilverStripe\Control\RSS\RSSFeed; use SilverStripe\Control\RSS\RSSFeed;
@ -25,8 +14,7 @@ use SilverStripe\Versioned\Versioned_Version;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\View\Requirements; use SilverStripe\View\Requirements;
use SilverStripe\Core\Extension; use SilverStripe\Core\Extension;
use SilverStripe\VersionFeed\Filters\ContentFilter;
class VersionFeed_Controller extends Extension { class VersionFeed_Controller extends Extension {
@ -38,16 +26,16 @@ class VersionFeed_Controller extends Extension {
/** /**
* Content handler * Content handler
* *
* @var \VersionFeed\Filters\ContentFilter * @var ContentFilter
*/ */
protected $contentFilter; protected $contentFilter;
/** /**
* Sets the content filter * Sets the content filter
* *
* @param \VersionFeed\Filters\ContentFilter $contentFilter * @param ContentFilter $contentFilter
*/ */
public function setContentFilter(\VersionFeed\Filters\ContentFilter $contentFilter) { public function setContentFilter(ContentFilter $contentFilter) {
$this->contentFilter = $contentFilter; $this->contentFilter = $contentFilter;
} }

View File

@ -2,16 +2,14 @@
namespace SilverStripe\VersionFeed\Tests; namespace SilverStripe\VersionFeed\Tests;
use SS_Cache;
use Zend_Cache;
use Page; use Page;
use SilverStripe\VersionFeed\VersionFeed; use SilverStripe\VersionFeed\VersionFeed;
use SilverStripe\VersionFeed\Filters\CachedContentFilter;
use SilverStripe\VersionFeed\Filters\RateLimitFilter;
use SilverStripe\VersionFeed\VersionFeedController; use SilverStripe\VersionFeed\VersionFeedController;
use SilverStripe\Core\Config\Config; use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\CMS\Model\SiteTree; use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
use SilverStripe\SiteConfig\SiteConfig; use SilverStripe\SiteConfig\SiteConfig;
@ -21,7 +19,7 @@ use SilverStripe\Dev\FunctionalTest;
class VersionFeedFunctionalTest extends FunctionalTest { class VersionFeedFunctionalTest extends FunctionalTest {
protected $usesDatabase = true; protected $usesDatabase = true;
protected $requiredExtensions = array( protected $required_extensions = array(
'Page' => array(VersionFeed::class), 'Page' => array(VersionFeed::class),
'Page_Controller' => array(VersionFeedController::class), 'Page_Controller' => array(VersionFeedController::class),
); );
@ -31,8 +29,10 @@ class VersionFeedFunctionalTest extends FunctionalTest {
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$cache = SS_Cache::factory(VersionFeedController::class); $cache = Injector::inst()->get(
$cache->clean(Zend_Cache::CLEANING_MODE_ALL); CacheInterface::class . '.' . VersionFeedController::class
);
$cache->clear();
$this->userIP = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : null; $this->userIP = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : null;
@ -42,11 +42,11 @@ class VersionFeedFunctionalTest extends FunctionalTest {
Config::inst()->update(VersionFeed::class, 'allchanges_enabled', true); Config::inst()->update(VersionFeed::class, 'allchanges_enabled', true);
// Disable caching and locking by default // Disable caching and locking by default
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', false); Config::inst()->update(CachedContentFilter::class, 'cache_enabled', false);
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 0); Config::inst()->update(RateLimitFilter::class, 'lock_timeout', 0);
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', false); Config::inst()->update(RateLimitFilter::class, 'lock_bypage', false);
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false); Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', false);
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_cooldown', false); Config::inst()->update(RateLimitFilter::class, 'lock_cooldown', false);
} }
public function tearDown() { public function tearDown() {
@ -83,17 +83,18 @@ class VersionFeedFunctionalTest extends FunctionalTest {
public function testRateLimiting() { public function testRateLimiting() {
// Re-enable locking just for this test // Re-enable locking just for this test
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 20); Config::inst()->update(RateLimitFilter::class, 'lock_timeout', 20);
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', true); Config::inst()->update(CachedContentFilter::class, 'cache_enabled', true);
$page1 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page1')); $page1 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page1'));
$page2 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page2')); $page2 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page2'));
// Artifically set cache lock // Artifically set cache lock
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false); Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', false);
$cache = SS_Cache::factory(VersionFeedController::class); $cache = Injector::inst()->get(
$cache->setOption('automatic_serialization', true); CacheInterface::class . '.' . VersionFeedController::class
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX); );
$cache->set(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX);
// Test normal hit // Test normal hit
$response = $this->get($page1->RelativeLink('changes')); $response = $this->get($page1->RelativeLink('changes'));
@ -104,39 +105,39 @@ class VersionFeedFunctionalTest extends FunctionalTest {
$this->assertGreaterThan(0, $response->getHeader('Retry-After')); $this->assertGreaterThan(0, $response->getHeader('Retry-After'));
// Test page specific lock // Test page specific lock
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', true); Config::inst()->update(RateLimitFilter::class, 'lock_bypage', true);
$key = implode('_', array( $key = implode('_', array(
'changes', 'changes',
$page1->ID, $page1->ID,
Versioned::get_versionnumber_by_stage(SiteTree::class, 'Live', $page1->ID, false) Versioned::get_versionnumber_by_stage(SiteTree::class, 'Live', $page1->ID, false)
)); ));
$key = \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5($key); $key = \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5($key);
$cache->save(time() + 10, $key); $cache->set(time() + 10, $key);
$response = $this->get($page1->RelativeLink('changes')); $response = $this->get($page1->RelativeLink('changes'));
$this->assertEquals(429, $response->getStatusCode()); $this->assertEquals(429, $response->getStatusCode());
$this->assertGreaterThan(0, $response->getHeader('Retry-After')); $this->assertGreaterThan(0, $response->getHeader('Retry-After'));
$response = $this->get($page2->RelativeLink('changes')); $response = $this->get($page2->RelativeLink('changes'));
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', false); Config::inst()->update(RateLimitFilter::class, 'lock_bypage', false);
// Test rate limit hit by IP // Test rate limit hit by IP
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', true); Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', true);
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1'; $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1')); $cache->set(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
$response = $this->get($page1->RelativeLink('changes')); $response = $this->get($page1->RelativeLink('changes'));
$this->assertEquals(429, $response->getStatusCode()); $this->assertEquals(429, $response->getStatusCode());
$this->assertGreaterThan(0, $response->getHeader('Retry-After')); $this->assertGreaterThan(0, $response->getHeader('Retry-After'));
// Test rate limit doesn't hit other IP // Test rate limit doesn't hit other IP
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.20'; $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.20';
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1')); $cache->set(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
$response = $this->get($page1->RelativeLink('changes')); $response = $this->get($page1->RelativeLink('changes'));
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
// Restore setting // Restore setting
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false); Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', false);
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 0); Config::inst()->update(RateLimitFilter::class, 'lock_timeout', 0);
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', false); Config::inst()->update(CachedContentFilter::class, 'cache_enabled', false);
} }
public function testContainsChangesForPageOnly() { public function testContainsChangesForPageOnly() {

View File

@ -13,7 +13,7 @@ class VersionFeedTest extends SapphireTest {
protected $usesDatabase = true; protected $usesDatabase = true;
protected $requiredExtensions = array( protected $required_extensions = array(
'SiteTree' => array(VersionFeed::class), 'SiteTree' => array(VersionFeed::class),
'ContentController' => array(VersionFeedController::class), 'ContentController' => array(VersionFeedController::class),
); );