Ticket #110 (closed defect: fixed)

Opened 6 months ago

Last modified 2 months ago

Solar_Sql_Adapter: cache conflict using two connections

Reported by: moraes Assigned to: pmjones
Priority: minor Component: code
Keywords: Solar_Sql_Adapter Cc:

Description

It seems that Solar_Sql_Adapter won't let you open two connections and use a cache at the same time, because before each connection $_cache_key_prefix will be empty. What I discovered was the following:

1. You call a model that uses database A. It'll call fetchTableList() which will try to get the list from cache. Because $_cache_key_prefix is created only on connect(), the cache name becomes simply '/fetchTableList'.

2. Tables are fetched for the first instance and the table list is cached as '/fetchTableList'.

3. You call a second model that uses database B. (1) happens again, but this time it finds a cached table list saved as '/fetchTableList' and which corresponds to the database A tables. The list is wrong, collision happens, etc.

My quick solution was to call connect() on _getCacheKey(), so that $_cache_key_prefix will never be empty, but perhaps the cache key can be configurable instead.

Attachments

Change History

04/21/08 13:37:38 changed by rodrigo.moraes at gmail.com

Here's a diff with a solution that doesn't require connect().

  • A property $_dsn stores the dsn for when it is needed (to connect or create the cache prefix).
  • _setCacheKeyPrefix() creates the prefix when it is not set, also setting the $_dsn value.
  • Done! No more conflicts.

Index: Solar/Sql/Adapter.php
===================================================================
--- Solar/Sql/Adapter.php	(revision 3125)
+++ Solar/Sql/Adapter.php	(working copy)
@@ -229,6 +229,15 @@
      * 
      */
     protected $_profiling = false;
+
+    /**
+     * 
+     * A PDO-style DSN, for example, "mysql:host=127.0.0.1;dbname=test"
+     * 
+     * @var string
+     * 
+     */
+    protected $_dsn;
     
     /**
      * 
@@ -301,6 +310,10 @@
      */
     protected function _dsn()
     {
+	    if ($this->_dsn) {
+		    return $this->_dsn;		
+	    }
+	
         $dsn = array();
         
         if (! empty($this->_config['host'])) {
@@ -315,7 +328,9 @@
             $dsn[] = 'dbname=' . $this->_config['name'];
         }
         
-        return $this->_pdo_type . ':' . implode(';', $dsn);
+        $this->_dsn = $this->_pdo_type . ':' . implode(';', $dsn);
+
+        return $this->_dsn;
     }
     
     /**
@@ -337,15 +352,12 @@
         // start profile time
         $before = microtime(true);
         
-        // build a DSN
-        $dsn = $this->_dsn();
+        // set the cache-key prefix, which will build a DSN 
+        $this->_setCacheKeyPrefix();
         
-        // save the cache-key prefix
-        $this->_cache_key_prefix = get_class($this) . '/' . md5($dsn);
-        
         // attempt the connection
         $this->_pdo = new PDO(
-            $dsn,
+            $this->_dsn,
             $this->_config['user'],
             $this->_config['pass']
         );
@@ -399,6 +411,16 @@
     {
         $this->_pdo = null;
     }
+
+    /**
+     * 
+     * Sets a cache key prefix.
+     * 
+     */
+    protected function _setCacheKeyPrefix()
+    {
+        $this->_cache_key_prefix = get_class($this) . '/' . md5($this->_dsn());
+    }
     
     /**
      * 
@@ -411,6 +433,12 @@
      */
     protected function _getCacheKey($key)
     {
+	    // create a prefix if not already set.
+	    if (! $this->_cache_key_prefix) {
+		    $this->_setCacheKeyPrefix();
+	    }
+	        
+        // save the cache-key prefix
         return $this->_cache_key_prefix . "/$key";
     }

04/23/08 16:04:10 changed by rodrigo.moraes at gmail.com

And now a much simpler diff: $_dsn and $_cache_key_prefix are simply created on construction instead of connect(), as needed to avoid conflicts with multiple connections.

Index: Solar/Sql/Adapter.php
===================================================================
--- Solar/Sql/Adapter.php	(revision 3125)
+++ Solar/Sql/Adapter.php	(working copy)
@@ -229,6 +229,15 @@
      * 
      */
     protected $_profiling = false;
+
+    /**
+     * 
+     * A PDO-style DSN, for example, "mysql:host=127.0.0.1;dbname=test"
+     * 
+     * @var string
+     * 
+     */
+    protected $_dsn;
     
     /**
      * 
@@ -242,6 +251,12 @@
         parent::__construct($config);
         $this->_cache = Solar::dependency('Solar_Cache', $this->_config['cache']);
         $this->setProfiling($this->_config['profiling']);
+        
+        // build a DSN
+        $this->_dsn = $this->_dsn();
+        
+        // save the cache-key prefix
+        $this->_cache_key_prefix = get_class($this) . '/' . md5($this->_dsn);
     }
     
     /**
@@ -337,15 +352,9 @@
         // start profile time
         $before = microtime(true);
         
-        // build a DSN
-        $dsn = $this->_dsn();
-        
-        // save the cache-key prefix
-        $this->_cache_key_prefix = get_class($this) . '/' . md5($dsn);
-        
         // attempt the connection
         $this->_pdo = new PDO(
-            $dsn,
+            $this->_dsn,
             $this->_config['user'],
             $this->_config['pass']
         );

05/03/08 15:45:47 changed by pmjones

  • status changed from new to closed.
  • resolution set to fixed.

Fixed in [3146]. Thanks Rodrigo.


Add/Change #110 (Solar_Sql_Adapter: cache conflict using two connections)




Action