Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii - Does database dependency caching work across multiple actions?

Tags:

caching

yii

Take this piece of code as an example:

public function actionPostOneWay( $postId )
{
    $dependency = new CDbCacheDependency( 'SELECT publish_date FROM posts WHERE id = :post_id;' );
    $dependency->params = array( 'post_id'=>$postId );
    $post = Post::model()->cache( 59, $dependency )->findByPk( $postId );

    // process post one way
}

public function actionPostAnotherWay( $postId )
{
    $dependency = new CDbCacheDependency( 'SELECT publish_date FROM posts WHERE id = :post_id;' );
    $dependency->params = array( 'post_id'=>$postId );
    $post = Post::model()->cache( 59, $dependency )->findByPk( $postId );

    // process post another way
}

So will accessing /postOneWay and /postAnotherWay reuse the same cached object, or will they create cache objects of their own?

like image 446
HyderA Avatar asked Nov 04 '12 10:11

HyderA


1 Answers

I tried to cache the same query in two different actions and yes, the same cached object will be used. One can see that enabling CProfileLogRoute in application's configuration file.

Looking at the source code of CActiveRecord class I stated that public function findByPk($pk,$condition='',$params=array()) method (and other query methods) use protected function query($criteria,$all=false). This one, in turn, finally relies on private function queryInternal($method,$mode,$params=array()) of CDbCommand class where Yii makes its caching work with database queries.

As one can see a cache key used to store and restore queries' results is defined as follows:

$cacheKey='yii:dbquery'.$this->_connection->connectionString.':'.$this->_connection->username;
$cacheKey.=':'.$this->getText().':'.serialize(array_merge($this->_paramLog,$params));
if(($result=$cache->get($cacheKey))!==false)
{
    Yii::trace('Query result found in cache','system.db.CDbCommand');
    return $result;
}

This key doesn't take a cache dependency instance into consideration. CDbCacheDependency is only used to determine whether something is changed in database and new query is to be executed to update the cache. To say more - if you specify different SQLs to create CDbCacheDependency in two actions only one of them (executed first) will make sense during caching time due to the instance of CDbCacheDependency is cached serialized along with query's result:

if(isset($cache,$cacheKey))
    $cache->set($cacheKey, $result, $this->_connection->queryCachingDuration, $this->_connection->queryCachingDependency);

Caching an instance of evaluated dependency could be seen in public function set($id,$value,$expire=0,$dependency=null) method of CCache class:

if ($dependency !== null && $this->serializer !== false)
    $dependency->evaluateDependency();

if ($this->serializer === null)
    $value = serialize(array($value,$dependency));
elseif ($this->serializer !== false)
    $value = call_user_func($this->serializer[0], array($value,$dependency));
like image 55
ezze Avatar answered Oct 12 '22 08:10

ezze