Browse Source

Started refactoring the ORM Cache Shell

Florian Krämer 8 years ago
parent
commit
b0d7c67b01
3 changed files with 138 additions and 55 deletions
  1. 115 0
      src/ORM/OrmCache.php
  2. 21 53
      src/Shell/OrmCacheShell.php
  3. 2 2
      tests/TestCase/Shell/OrmCacheShellTest.php

+ 115 - 0
src/ORM/OrmCache.php

@@ -0,0 +1,115 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ * @link          https://cakephp.org CakePHP(tm) Project
+ * @since         3.0.0
+ * @license       https://opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Orm;
+
+use Cake\Cache\Cache;
+use Cake\Datasource\ConnectionManager;
+
+/**
+ * ORM Cache.
+ *
+ * This tool is intended to be used by deployment scripts so that you
+ * can prevent thundering herd effects on the metadata cache when new
+ * versions of your application are deployed, or when migrations
+ * requiring updated metadata are required.
+ */
+class OrmCache
+{
+
+    /**
+     * Schema
+     *
+     * @var \Cake\Datasource\SchemaInterface
+     */
+    protected $_schema;
+
+    /**
+     * Constructor
+     *
+     * @param string $connection Connection name
+     */
+    public function __construct($connection)
+    {
+        $this->_schema = $this->getSchema($connection);
+    }
+
+    /**
+     * Build metadata.
+     *
+     * @param string|null $name The name of the table to build cache data for.
+     * @return bool
+     */
+    public function build($name = null)
+    {
+        $tables = [$name];
+        if (empty($name)) {
+            $tables = $this->_schema->listTables();
+        }
+
+        foreach ($tables as $table) {
+            $this->_schema->describe($table, ['forceRefresh' => true]);
+        }
+
+        return true;
+    }
+
+    /**
+     * Clear metadata.
+     *
+     * @param string|null $name The name of the table to clear cache data for.
+     * @return bool
+     */
+    public function clear($name = null)
+    {
+        $tables = [$name];
+        if (empty($name)) {
+            $tables = $this->_schema->listTables();
+        }
+        $configName = $this->_schema->getCacheMetadata();
+
+        foreach ($tables as $table) {
+            $key = $this->_schema->cacheKey($table);
+            Cache::delete($key, $configName);
+        }
+
+        return true;
+    }
+
+    /**
+     * Helper method to get the schema collection.
+     *
+     * @param string $connection Connection name to get the schema for
+     * @return false|\Cake\Database\Schema\Collection|\Cake\Database\Schema\CachedCollection
+     */
+    public function getSchema($connection)
+    {
+        /* @var \Cake\Database\Connection $source */
+        $source = ConnectionManager::get($connection);
+        if (!method_exists($source, 'schemaCollection')) {
+            throw new RuntimeException(sprintf(
+                'The "%s" connection is not compatible with orm caching, ' .
+                'as it does not implement a "schemaCollection()" method.',
+                $connection
+            ));
+        }
+
+        $config = $source->config();
+        if (empty($config['cacheMetadata'])) {
+            $source->cacheMetadata(true);
+        }
+
+        return $source->getSchemaCollection();
+    }
+}

+ 21 - 53
src/Shell/OrmCacheShell.php

@@ -14,9 +14,9 @@
  */
 namespace Cake\Shell;
 
-use Cake\Cache\Cache;
 use Cake\Console\Shell;
-use Cake\Datasource\ConnectionManager;
+use Cake\Orm\OrmCache;
+use RuntimeException;
 
 /**
  * ORM Cache Shell.
@@ -31,6 +31,13 @@ class OrmCacheShell extends Shell
 {
 
     /**
+     * ORM Cache
+     *
+     * @var \Cake\ORM\OrmCache
+     */
+    protected $_ormCache;
+
+    /**
      * Build metadata.
      *
      * @param string|null $name The name of the table to build cache data for.
@@ -38,18 +45,9 @@ class OrmCacheShell extends Shell
      */
     public function build($name = null)
     {
-        $schema = $this->_getSchema();
-        if (!$schema) {
-            return false;
-        }
-        $tables = [$name];
-        if (empty($name)) {
-            $tables = $schema->listTables();
-        }
-        foreach ($tables as $table) {
-            $this->_io->verbose('Building metadata cache for ' . $table);
-            $schema->describe($table, ['forceRefresh' => true]);
-        }
+        $cache = $this->_getOrmCache();
+        $cache->build($name);
+
         $this->out('<success>Cache build complete</success>');
 
         return true;
@@ -63,56 +61,26 @@ class OrmCacheShell extends Shell
      */
     public function clear($name = null)
     {
-        $schema = $this->_getSchema();
-        if (!$schema) {
-            return false;
-        }
-        $tables = [$name];
-        if (empty($name)) {
-            $tables = $schema->listTables();
-        }
-        $configName = $schema->getCacheMetadata();
+        $cache = $this->_getOrmCache();
+        $cache->clear($name);
 
-        foreach ($tables as $table) {
-            $this->_io->verbose(sprintf(
-                'Clearing metadata cache from "%s" for %s',
-                $configName,
-                $table
-            ));
-            $key = $schema->cacheKey($table);
-            Cache::delete($key, $configName);
-        }
         $this->out('<success>Cache clear complete</success>');
 
         return true;
     }
 
     /**
-     * Helper method to get the schema collection.
+     * Gets the ORM Cache instance
      *
-     * @return false|\Cake\Database\Schema\Collection|\Cake\Database\Schema\CachedCollection
+     * @return \Cake\ORM\OrmCache
      */
-    protected function _getSchema()
+    protected function _getOrmCache()
     {
-        /* @var \Cake\Database\Connection $source */
-        $source = ConnectionManager::get($this->params['connection']);
-        if (!method_exists($source, 'schemaCollection')) {
-            $msg = sprintf(
-                'The "%s" connection is not compatible with orm caching, ' .
-                'as it does not implement a "schemaCollection()" method.',
-                $this->params['connection']
-            );
-            $this->abort($msg);
-
-            return false;
-        }
-        $config = $source->config();
-        if (empty($config['cacheMetadata'])) {
-            $this->_io->verbose('Metadata cache was disabled in config. Enabling to clear cache.');
-            $source->cacheMetadata(true);
+        try {
+            return new OrmCache($this->params['connection']);
+        } catch (RuntimeException $e) {
+            $this->abort($e->getMessage());
         }
-
-        return $source->getSchemaCollection();
     }
 
     /**

+ 2 - 2
tests/TestCase/Shell/OrmCacheShellTest.php

@@ -151,7 +151,7 @@ class OrmCacheShellTest extends TestCase
     /**
      * Test build() with a non-existing connection name.
      *
-     * @expectedException \Cake\Datasource\Exception\MissingDatasourceConfigException
+     * @expectedException \Cake\Console\Exception\StopException
      * @return void
      */
     public function testBuildInvalidConnection()
@@ -163,7 +163,7 @@ class OrmCacheShellTest extends TestCase
     /**
      * Test clear() with an invalid connection name.
      *
-     * @expectedException \Cake\Datasource\Exception\MissingDatasourceConfigException
+     * @expectedException \Cake\Console\Exception\StopException
      * @return void
      */
     public function testClearInvalidConnection()